<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  <meta name="renderer" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=edge" >
  <link rel="dns-prefetch" href="http://eason_mo.gitee.io/blog">
  <title>游走的提莫</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta property="og:type" content="website">
<meta property="og:title" content="游走的提莫">
<meta property="og:url" content="http://eason_mo.gitee.io/blog/index.html">
<meta property="og:site_name" content="游走的提莫">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="CozyMo">
<meta name="twitter:card" content="summary">
  
    <link rel="alternative" href="/atom.xml" title="游走的提莫" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png">
  
  <link rel="stylesheet" type="text/css" href="/blog/./main.0cf68a.css">
  <style type="text/css">
  
    #container.show {
      background: linear-gradient(200deg,#a0cfe4,#e8c37e);
    }
  </style>
  

  

<meta name="generator" content="Hexo 4.2.0"></head>

<body>
  <div id="container" q-class="show:isCtnShow">
    <canvas id="anm-canvas" class="anm-canvas"></canvas>
    <div class="left-col" q-class="show:isShow">
      
<div class="overlay" style="background: #4d4d4d"></div>
<div class="intrude-less">
	<header id="header" class="inner">
		<a href="/" class="profilepic">
			<img src="./img/maomao.jpg" class="js-avatar">
		</a>
		<hgroup>
		  <h1 class="header-author"><a href="/">CozyMo</a></h1>
		</hgroup>
		

		<nav class="header-menu">
			<ul>
			
				<li><a href="/blog/">主页</a></li>
	        
				<li><a href="/blog/tags/%E9%9A%8F%E7%AC%94/">随笔</a></li>
	        
			</ul>
		</nav>
		<nav class="header-smart-menu">
    		
    			
    			<a q-on="click: openSlider(e, 'innerArchive')" href="javascript:void(0)">所有文章</a>
    			
            
    			
    			<a q-on="click: openSlider(e, 'friends')" href="javascript:void(0)">友链</a>
    			
            
    			
    			<a q-on="click: openSlider(e, 'aboutme')" href="javascript:void(0)">关于我</a>
    			
            
		</nav>
		<nav class="header-nav">
			<div class="social">
				
					<a class="github" target="_blank" href="#" title="github"><i class="icon-github"></i></a>
		        
					<a class="weibo" target="_blank" href="#" title="weibo"><i class="icon-weibo"></i></a>
		        
					<a class="rss" target="_blank" href="#" title="rss"><i class="icon-rss"></i></a>
		        
					<a class="zhihu" target="_blank" href="#" title="zhihu"><i class="icon-zhihu"></i></a>
		        
			</div>
		</nav>
	</header>		
</div>

    </div>
    <div class="mid-col" q-class="show:isShow,hide:isShow|isFalse">
      
<nav id="mobile-nav">
  	<div class="overlay js-overlay" style="background: #4d4d4d"></div>
	<div class="btnctn js-mobile-btnctn">
  		<div class="slider-trigger list" q-on="click: openSlider(e)"><i class="icon icon-sort"></i></div>
	</div>
	<div class="intrude-less">
		<header id="header" class="inner">
			<div class="profilepic">
				<img src="./img/maomao.jpg" class="js-avatar">
			</div>
			<hgroup>
			  <h1 class="header-author js-header-author">CozyMo</h1>
			</hgroup>
			
			
			
				
			
				
			
			
			
			<nav class="header-nav">
				<div class="social">
					
						<a class="github" target="_blank" href="#" title="github"><i class="icon-github"></i></a>
			        
						<a class="weibo" target="_blank" href="#" title="weibo"><i class="icon-weibo"></i></a>
			        
						<a class="rss" target="_blank" href="#" title="rss"><i class="icon-rss"></i></a>
			        
						<a class="zhihu" target="_blank" href="#" title="zhihu"><i class="icon-zhihu"></i></a>
			        
				</div>
			</nav>

			<nav class="header-menu js-header-menu">
				<ul style="width: 50%">
				
				
					<li style="width: 50%"><a href="/blog/">主页</a></li>
		        
					<li style="width: 50%"><a href="/blog/tags/%E9%9A%8F%E7%AC%94/">随笔</a></li>
		        
				</ul>
			</nav>
		</header>				
	</div>
	<div class="mobile-mask" style="display:none" q-show="isShow"></div>
</nav>

      <div id="wrapper" class="body-wrap">
        <div class="menu-l">
          <div class="canvas-wrap">
            <canvas data-colors="#eaeaea" data-sectionHeight="100" data-contentId="js-content" id="myCanvas1" class="anm-canvas"></canvas>
          </div>
          <div id="js-content" class="content-ll">
            
  
    <article id="post-drf序列化和反序列化" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/04/05/drf%E5%BA%8F%E5%88%97%E5%8C%96%E5%92%8C%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/">drf序列化和反序列化</a>
    </h1>
  

        
        <a href="/blog/2020/04/05/drf%E5%BA%8F%E5%88%97%E5%8C%96%E5%92%8C%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/" class="archive-article-date">
  	<time datetime="2020-04-05T07:51:54.709Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2020-04-05</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id=""><a href="#" class="headerlink" title=""></a></h2><h5 id="配置：settings-py"><a href="#配置：settings-py" class="headerlink" title="配置：settings.py"></a>配置：settings.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">INSTALLED_APPS = [</span><br><span class="line">    <span class="comment"># ...</span></span><br><span class="line">    <span class="string">'rest_framework'</span>,</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line">DATABASES = &#123;</span><br><span class="line">    <span class="string">'default'</span>: &#123;</span><br><span class="line">        <span class="string">'ENGINE'</span>: <span class="string">'django.db.backends.mysql'</span>,</span><br><span class="line">        <span class="string">'NAME'</span>: <span class="string">'dg_proj'</span>,</span><br><span class="line">        <span class="string">'USER'</span>: <span class="string">'root'</span>,</span><br><span class="line">        <span class="string">'PASSWORD'</span>: <span class="string">'123'</span>,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">任何__init__文件</span></span><br><span class="line"><span class="string">import pymysql</span></span><br><span class="line"><span class="string">pymysql.install_as_MySQLdb()</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 国际化配置</span></span><br><span class="line">LANGUAGE_CODE = <span class="string">'zh-hans'</span></span><br><span class="line">TIME_ZONE = <span class="string">'Asia/Shanghai'</span></span><br><span class="line">USE_I18N = <span class="literal">True</span></span><br><span class="line">USE_L10N = <span class="literal">True</span></span><br><span class="line">USE_TZ = <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">MEDIA_URL = <span class="string">'/media/'</span></span><br><span class="line">MEDIA_ROOT = os.path.join(BASE_DIR, <span class="string">'media'</span>)</span><br></pre></td></tr></table></figure>

<h5 id="路由"><a href="#路由" class="headerlink" title="路由"></a>路由</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 主</span></span><br><span class="line"><span class="keyword">from</span> django.conf.urls <span class="keyword">import</span> url, include</span><br><span class="line"><span class="keyword">from</span> django.contrib <span class="keyword">import</span> admin</span><br><span class="line"><span class="keyword">from</span> django.views.static <span class="keyword">import</span> serve</span><br><span class="line"><span class="keyword">from</span> django.conf <span class="keyword">import</span> settings</span><br><span class="line">urlpatterns = [</span><br><span class="line">    url(<span class="string">r'^admin/'</span>, admin.site.urls),</span><br><span class="line">    url(<span class="string">r'^api/'</span>, include(<span class="string">'api.urls'</span>)),</span><br><span class="line">    url(<span class="string">r'^media/(?P&lt;path&gt;.*)'</span>, serve, &#123;<span class="string">'document_root'</span>: settings.MEDIA_ROOT&#125;),</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"><span class="comment"># 子</span></span><br><span class="line"><span class="keyword">from</span> django.conf.urls <span class="keyword">import</span> url</span><br><span class="line"><span class="keyword">from</span> . <span class="keyword">import</span> views</span><br><span class="line">urlpatterns = [</span><br><span class="line">    </span><br><span class="line">]</span><br></pre></td></tr></table></figure>



<h2 id="多表设计"><a href="#多表设计" class="headerlink" title="多表设计"></a>多表设计</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">Book表：name、price、img、authors、publish、is_delete、create_time</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">Publish表：name、address、is_delete、create_time</span></span><br><span class="line"><span class="string">	</span></span><br><span class="line"><span class="string">Author表：name、age、is_delete、create_time</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">AuthorDetail表：mobile, author、is_delete、create_time</span></span><br><span class="line"><span class="string">	</span></span><br><span class="line"><span class="string">BaseModel基表</span></span><br><span class="line"><span class="string">	is_delete、create_time</span></span><br><span class="line"><span class="string">上面四表继承基表，可以继承两个字段</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></table></figure>

<h2 id="基表"><a href="#基表" class="headerlink" title="基表"></a>基表</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BaseModel</span><span class="params">(models.Model)</span>:</span></span><br><span class="line">    is_delete = models.BooleanField(default=<span class="literal">False</span>)</span><br><span class="line">    create_time = models.DateTimeField(auto_now_add=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 设置 abstract = True 来声明基表，作为基表的Model不能在数据库中形成对应的表</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        abstract = <span class="literal">True</span></span><br></pre></td></tr></table></figure>



<h2 id="断关联多表关系"><a href="#断关联多表关系" class="headerlink" title="断关联多表关系"></a>断关联多表关系</h2><h5 id="知识点（重点）"><a href="#知识点（重点）" class="headerlink" title="知识点（重点）"></a>知识点（重点）</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">1、外键位置：</span></span><br><span class="line"><span class="string">	一对多 - 外键放多的一方</span></span><br><span class="line"><span class="string">	一对一 - 从逻辑正反向考虑，如作者表与作者详情表，作者删除级联删除详情，详情删除作者依旧存在，所以建议外键在详情表中</span></span><br><span class="line"><span class="string">	多对多 - 外键在关系表中</span></span><br><span class="line"><span class="string">	</span></span><br><span class="line"><span class="string">2、ORM正向方向连表查找：</span></span><br><span class="line"><span class="string">	正向：通过外键字段 eg: author_detial_obj.author </span></span><br><span class="line"><span class="string">	反向：通过related_name的值 eg：author_obj.detail</span></span><br><span class="line"><span class="string">	注：依赖代码见下方</span></span><br><span class="line"><span class="string">	</span></span><br><span class="line"><span class="string">3、连表操作关系：</span></span><br><span class="line"><span class="string">	1）作者删除，详情级联 - on_delete=models.CASCADE</span></span><br><span class="line"><span class="string">	2）作者删除，详情置空 - null=True, on_delete=models.SET_NULL</span></span><br><span class="line"><span class="string">	3）作者删除，详情重置 - default=0, on_delete=models.SET_DEFAULT</span></span><br><span class="line"><span class="string">	4）作者删除，详情不动 - on_delete=models.DO_NOTHING</span></span><br><span class="line"><span class="string">	注：拿作者与作者详情表举例</span></span><br><span class="line"><span class="string">	</span></span><br><span class="line"><span class="string">4、外键关联字段的参数 - 如何实现 断关联、目前表间操作关系、方向查询字段</span></span><br><span class="line"><span class="string">	i）作者详情表中的</span></span><br><span class="line"><span class="string">	author = models.OneToOneField(</span></span><br><span class="line"><span class="string">		to='Author',</span></span><br><span class="line"><span class="string">        related_name='detail',</span></span><br><span class="line"><span class="string">        db_constraint=False,</span></span><br><span class="line"><span class="string">        on_delete=models.CASCADE</span></span><br><span class="line"><span class="string">    )</span></span><br><span class="line"><span class="string">    </span></span><br><span class="line"><span class="string">    ii）图书表中的</span></span><br><span class="line"><span class="string">    publish = models.ForeignKey(</span></span><br><span class="line"><span class="string">    	to='Publish',</span></span><br><span class="line"><span class="string">        related_name='books',</span></span><br><span class="line"><span class="string">        db_constraint=False,</span></span><br><span class="line"><span class="string">        on_delete=models.DO_NOTHING,</span></span><br><span class="line"><span class="string">    )</span></span><br><span class="line"><span class="string">    authors = models.ManyToManyField(</span></span><br><span class="line"><span class="string">    	to='Author'</span></span><br><span class="line"><span class="string">        related_name='books',</span></span><br><span class="line"><span class="string">        db_constraint=False,</span></span><br><span class="line"><span class="string">    )</span></span><br><span class="line"><span class="string">    注：ManyToManyField不能设置on_delete，OneToOneField、ForeignKey必须设置on_delete（django1.x系统默认级联，但是django2.x必须手动明确）</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></table></figure>

<h5 id="model类"><a href="#model类" class="headerlink" title="model类"></a>model类</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.db <span class="keyword">import</span> models</span><br><span class="line"></span><br><span class="line"><span class="comment"># 图书管理系统：Book、Author、AuthorDetail、Publish</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">Book表: name、price、img、authors、publish、is_delete、create_time</span></span><br><span class="line"><span class="string">Publish表: name、address、is_delete、create_time</span></span><br><span class="line"><span class="string">Author表: name、age、is_delete、create_time</span></span><br><span class="line"><span class="string">AuthorDetail表: mobile, author、is_delete、create_time</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 1) 基表</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BaseModel</span><span class="params">(models.Model)</span>:</span></span><br><span class="line">    is_delete = models.BooleanField(default=<span class="literal">False</span>)</span><br><span class="line">    create_time = models.DateTimeField(auto_now_add=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 作为基表的Model不能在数据库中形成对应的表，设置 abstract = True</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        abstract = <span class="literal">True</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Book</span><span class="params">(BaseModel)</span>:</span></span><br><span class="line">    <span class="string">"""name、price、img、authors、publish、is_delete、create_time"""</span></span><br><span class="line">    name = models.CharField(max_length=<span class="number">64</span>)</span><br><span class="line">    price = models.DecimalField(max_digits=<span class="number">5</span>, decimal_places=<span class="number">2</span>)</span><br><span class="line">    img = models.ImageField(upload_to=<span class="string">'img'</span>, default=<span class="string">'img/default.jpg'</span>)</span><br><span class="line">    publish = models.ForeignKey(</span><br><span class="line">        to=<span class="string">'Publish'</span>,</span><br><span class="line">        db_constraint=<span class="literal">False</span>,  <span class="comment"># 断关联</span></span><br><span class="line">        related_name=<span class="string">'books'</span>,  <span class="comment"># 反向查询字段：publish_obj.books 就能访问所有出版的书</span></span><br><span class="line">        on_delete=models.DO_NOTHING,  <span class="comment"># 设置连表操作关系</span></span><br><span class="line">    )</span><br><span class="line">    authors = models.ManyToManyField(</span><br><span class="line">        to=<span class="string">'Author'</span>,</span><br><span class="line">        db_constraint=<span class="literal">False</span>,</span><br><span class="line">        related_name=<span class="string">'books'</span></span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">	<span class="comment"># 序列化插拔式属性 - 完成自定义字段名完成连表查询</span></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">publish_name</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self.publish.name</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">author_list</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self.authors.values(<span class="string">'name'</span>, <span class="string">'age'</span>, <span class="string">'detail__mobile'</span>).all()</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        db_table = <span class="string">'book'</span></span><br><span class="line">        verbose_name = <span class="string">'书籍'</span></span><br><span class="line">        verbose_name_plural = verbose_name</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__str__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self.name</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Publish</span><span class="params">(BaseModel)</span>:</span></span><br><span class="line">    <span class="string">"""name、address、is_delete、create_time"""</span></span><br><span class="line">    name = models.CharField(max_length=<span class="number">64</span>)</span><br><span class="line">    address = models.CharField(max_length=<span class="number">64</span>)</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        db_table = <span class="string">'publish'</span></span><br><span class="line">        verbose_name = <span class="string">'出版社'</span></span><br><span class="line">        verbose_name_plural = verbose_name</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__str__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self.name</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Author</span><span class="params">(BaseModel)</span>:</span></span><br><span class="line">    <span class="string">"""name、age、is_delete、create_time"""</span></span><br><span class="line">    name = models.CharField(max_length=<span class="number">64</span>)</span><br><span class="line">    age = models.IntegerField()</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        db_table = <span class="string">'author'</span></span><br><span class="line">        verbose_name = <span class="string">'作者'</span></span><br><span class="line">        verbose_name_plural = verbose_name</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__str__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self.name</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">AuthorDetail</span><span class="params">(BaseModel)</span>:</span></span><br><span class="line">    <span class="string">"""mobile, author、is_delete、create_time"""</span></span><br><span class="line">    mobile = models.CharField(max_length=<span class="number">11</span>)</span><br><span class="line">    author = models.OneToOneField(</span><br><span class="line">        to=<span class="string">'Author'</span>,</span><br><span class="line">        db_constraint=<span class="literal">False</span>,</span><br><span class="line">        related_name=<span class="string">'detail'</span>,</span><br><span class="line">        on_delete=models.CASCADE,</span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        db_table = <span class="string">'author_detail'</span></span><br><span class="line">        verbose_name = <span class="string">'作者详情'</span></span><br><span class="line">        verbose_name_plural = verbose_name</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__str__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> <span class="string">'%s的详情'</span> % self.author.name</span><br></pre></td></tr></table></figure>





<h2 id="序列化"><a href="#序列化" class="headerlink" title="序列化"></a>序列化</h2><h5 id="序列化层：api-serializers-py"><a href="#序列化层：api-serializers-py" class="headerlink" title="序列化层：api/serializers.py"></a>序列化层：api/serializers.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> rest_framework.serializers <span class="keyword">import</span> ModelSerializer, SerializerMethodField</span><br><span class="line"><span class="keyword">from</span> rest_framework.exceptions <span class="keyword">import</span> ValidationError</span><br><span class="line"><span class="keyword">from</span> . <span class="keyword">import</span> models</span><br><span class="line"></span><br><span class="line"><span class="comment"># 可以单独作为Publish接口的序列化类，也可以作为Book序列化外键publish辅助的序列化组件</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">PublishModelSerializer</span><span class="params">(ModelSerializer)</span>:</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        model = models.Publish</span><br><span class="line">        fields = (<span class="string">'name'</span>, <span class="string">'address'</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookModelSerializer</span><span class="params">(ModelSerializer)</span>:</span></span><br><span class="line">    <span class="comment"># 了解: 该方式设置的序列化字段，必须在fields中声明</span></span><br><span class="line">    <span class="comment"># publish_address = SerializerMethodField()</span></span><br><span class="line">    <span class="comment"># def get_publish_address(self, obj):</span></span><br><span class="line">    <span class="comment">#     return obj.publish.address</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 自定义连表深度 - 子序列化方式 - 该方式不能参与反序列化，使用在序列化反序列化共存时，不能书写</span></span><br><span class="line">    publish = PublishModelSerializer()</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        <span class="comment"># 序列化类关联的model类</span></span><br><span class="line">        model = models.Book</span><br><span class="line">        <span class="comment"># 参与序列化的字段</span></span><br><span class="line">        fields = (<span class="string">'name'</span>, <span class="string">'price'</span>, <span class="string">'img'</span>, <span class="string">'author_list'</span>, <span class="string">'publish'</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 了解知识点</span></span><br><span class="line">        <span class="comment"># 所有字段</span></span><br><span class="line">        <span class="comment"># fields = '__all__'</span></span><br><span class="line">        <span class="comment"># 与fields不共存，exclude排除哪些字段</span></span><br><span class="line">        <span class="comment"># exclude = ('id', 'is_delete', 'create_time')</span></span><br><span class="line">        <span class="comment"># 自动连表深度</span></span><br><span class="line">        <span class="comment"># depth = 1</span></span><br></pre></td></tr></table></figure>

<h5 id="视图层：api-views-py"><a href="#视图层：api-views-py" class="headerlink" title="视图层：api/views.py"></a>视图层：api/views.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Book</span><span class="params">(APIView)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span><span class="params">(self, request, *args, **kwargs)</span>:</span></span><br><span class="line">        pk = kwargs.get(<span class="string">'pk'</span>)</span><br><span class="line">        <span class="keyword">if</span> pk:</span><br><span class="line">            <span class="keyword">try</span>:</span><br><span class="line">                book_obj = models.Book.objects.get(pk=pk, is_delete=<span class="literal">False</span>)</span><br><span class="line">                book_data = serializers.BookModelSerializer(book_obj).data</span><br><span class="line">            <span class="keyword">except</span>:</span><br><span class="line">                <span class="keyword">return</span> Response(&#123;</span><br><span class="line">                    <span class="string">'status'</span>: <span class="number">1</span>,</span><br><span class="line">                    <span class="string">'msg'</span>: <span class="string">'书籍不存在'</span></span><br><span class="line">                &#125;)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            book_query = models.Book.objects.filter(is_delete=<span class="literal">False</span>).all()</span><br><span class="line">            book_data = serializers.BookModelSerializer(book_query, many=<span class="literal">True</span>).data</span><br><span class="line">        <span class="keyword">return</span> Response(&#123;</span><br><span class="line">            <span class="string">'status'</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="string">'msg'</span>: <span class="string">'ok'</span>,</span><br><span class="line">            <span class="string">'results'</span>: book_data</span><br><span class="line">        &#125;)</span><br></pre></td></tr></table></figure>

<h5 id="路由层：api-urls-py"><a href="#路由层：api-urls-py" class="headerlink" title="路由层：api/urls.py"></a>路由层：api/urls.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">urlpatterns = [</span><br><span class="line">    url(<span class="string">r'^books/$'</span>, views.Book.as_view()),</span><br><span class="line">    url(<span class="string">r'^books/(?P&lt;pk&gt;.*)/$'</span>, views.Book.as_view()),</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<h2 id="反序列化"><a href="#反序列化" class="headerlink" title="反序列化"></a>反序列化</h2><h5 id="序列化层：api-serializers-py-1"><a href="#序列化层：api-serializers-py-1" class="headerlink" title="序列化层：api/serializers.py"></a>序列化层：api/serializers.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookModelDeserializer</span><span class="params">(ModelSerializer)</span>:</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        model = models.Book</span><br><span class="line">        fields = (<span class="string">'name'</span>, <span class="string">'price'</span>, <span class="string">'publish'</span>, <span class="string">'authors'</span>)</span><br><span class="line">        <span class="comment"># extra_kwargs 用来完成反序列化字段的 系统校验规则</span></span><br><span class="line">        extra_kwargs = &#123;</span><br><span class="line">            <span class="string">'name'</span>: &#123;</span><br><span class="line">                <span class="string">'required'</span>: <span class="literal">True</span>,</span><br><span class="line">                <span class="string">'min_length'</span>: <span class="number">1</span>,</span><br><span class="line">                <span class="string">'error_messages'</span>: &#123;</span><br><span class="line">                    <span class="string">'required'</span>: <span class="string">'必填项'</span>,</span><br><span class="line">                    <span class="string">'min_length'</span>: <span class="string">'太短'</span>,</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">	</span><br><span class="line">    <span class="comment"># 局部钩子</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">validate_name</span><span class="params">(self, value)</span>:</span></span><br><span class="line">        <span class="comment"># 书名不能包含 g 字符</span></span><br><span class="line">        <span class="keyword">if</span> <span class="string">'g'</span> <span class="keyword">in</span> value.lower():</span><br><span class="line">            <span class="keyword">raise</span> ValidationError(<span class="string">'该g书不能出版'</span>)</span><br><span class="line">        <span class="keyword">return</span> value</span><br><span class="line">	<span class="comment"># 全局钩子</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">validate</span><span class="params">(self, attrs)</span>:</span></span><br><span class="line">        publish = attrs.get(<span class="string">'publish'</span>)</span><br><span class="line">        name = attrs.get(<span class="string">'name'</span>)</span><br><span class="line">        <span class="keyword">if</span> models.Book.objects.filter(name=name, publish=publish):</span><br><span class="line">            <span class="keyword">raise</span> ValidationError(&#123;<span class="string">'book'</span>: <span class="string">'该书已存在'</span>&#125;)</span><br><span class="line">        <span class="keyword">return</span> attrs</span><br><span class="line"></span><br><span class="line">    <span class="comment"># ModelSerializer类已经帮我们实现了 create 与 update 方法</span></span><br></pre></td></tr></table></figure>

<h5 id="视图层：api-views-py-1"><a href="#视图层：api-views-py-1" class="headerlink" title="视图层：api/views.py"></a>视图层：api/views.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Book</span><span class="params">(APIView)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">post</span><span class="params">(self, request, *args, **kwargs)</span>:</span></span><br><span class="line">        request_data = request.data</span><br><span class="line">        book_ser = serializers.BookModelDeserializer(data=request_data)</span><br><span class="line">        <span class="comment"># raise_exception=True：当校验失败，马上终止当前视图方法，抛异常返回给前台</span></span><br><span class="line">        book_ser.is_valid(raise_exception=<span class="literal">True</span>)</span><br><span class="line">        book_obj = book_ser.save()</span><br><span class="line">        <span class="keyword">return</span> Response(&#123;</span><br><span class="line">            <span class="string">'status'</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="string">'msg'</span>: <span class="string">'ok'</span>,</span><br><span class="line">            <span class="string">'results'</span>: serializers.BookModelSerializer(book_obj).data</span><br><span class="line">        &#125;)</span><br></pre></td></tr></table></figure>

<h5 id="路由层：api-urls-py-1"><a href="#路由层：api-urls-py-1" class="headerlink" title="路由层：api/urls.py"></a>路由层：api/urls.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">urlpatterns = [</span><br><span class="line">    url(<span class="string">r'^books/$'</span>, views.Book.as_view()),</span><br><span class="line">    url(<span class="string">r'^books/(?P&lt;pk&gt;.*)/$'</span>, views.Book.as_view()),</span><br><span class="line">]</span><br></pre></td></tr></table></figure>





<h2 id="序列化与反序列化整合（重点）"><a href="#序列化与反序列化整合（重点）" class="headerlink" title="序列化与反序列化整合（重点）"></a>序列化与反序列化整合（重点）</h2><h5 id="序列化层：api-serializers-py-2"><a href="#序列化层：api-serializers-py-2" class="headerlink" title="序列化层：api/serializers.py"></a>序列化层：api/serializers.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">1) fields中设置所有序列化与反序列化字段</span></span><br><span class="line"><span class="string">2) extra_kwargs划分只序列化或只反序列化字段</span></span><br><span class="line"><span class="string">    write_only：只反序列化</span></span><br><span class="line"><span class="string">    read_only：只序列化</span></span><br><span class="line"><span class="string">    自定义字段默认只序列化(read_only)</span></span><br><span class="line"><span class="string">3) 设置反序列化所需的 系统、局部钩子、全局钩子 等校验规则</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">V2BookModelSerializer</span><span class="params">(ModelSerializer)</span>:</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        model = models.Book</span><br><span class="line">        fields = (<span class="string">'name'</span>, <span class="string">'price'</span>, <span class="string">'img'</span>, <span class="string">'author_list'</span>, <span class="string">'publish_name'</span>, <span class="string">'publish'</span>, <span class="string">'authors'</span>)</span><br><span class="line">        extra_kwargs = &#123;</span><br><span class="line">            <span class="string">'name'</span>: &#123;</span><br><span class="line">                <span class="string">'required'</span>: <span class="literal">True</span>,</span><br><span class="line">                <span class="string">'min_length'</span>: <span class="number">1</span>,</span><br><span class="line">                <span class="string">'error_messages'</span>: &#123;</span><br><span class="line">                    <span class="string">'required'</span>: <span class="string">'必填项'</span>,</span><br><span class="line">                    <span class="string">'min_length'</span>: <span class="string">'太短'</span>,</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="string">'publish'</span>: &#123;</span><br><span class="line">                <span class="string">'write_only'</span>: <span class="literal">True</span></span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="string">'authors'</span>: &#123;</span><br><span class="line">                <span class="string">'write_only'</span>: <span class="literal">True</span></span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="string">'img'</span>: &#123;</span><br><span class="line">                <span class="string">'read_only'</span>: <span class="literal">True</span>,</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="string">'author_list'</span>: &#123;</span><br><span class="line">                <span class="string">'read_only'</span>: <span class="literal">True</span>,</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="string">'publish_name'</span>: &#123;</span><br><span class="line">                <span class="string">'read_only'</span>: <span class="literal">True</span>,</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">validate_name</span><span class="params">(self, value)</span>:</span></span><br><span class="line">        <span class="comment"># 书名不能包含 g 字符</span></span><br><span class="line">        <span class="keyword">if</span> <span class="string">'g'</span> <span class="keyword">in</span> value.lower():</span><br><span class="line">            <span class="keyword">raise</span> ValidationError(<span class="string">'该g书不能出版'</span>)</span><br><span class="line">        <span class="keyword">return</span> value</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">validate</span><span class="params">(self, attrs)</span>:</span></span><br><span class="line">        publish = attrs.get(<span class="string">'publish'</span>)</span><br><span class="line">        name = attrs.get(<span class="string">'name'</span>)</span><br><span class="line">        <span class="keyword">if</span> models.Book.objects.filter(name=name, publish=publish):</span><br><span class="line">            <span class="keyword">raise</span> ValidationError(&#123;<span class="string">'book'</span>: <span class="string">'该书已存在'</span>&#125;)</span><br><span class="line">        <span class="keyword">return</span> attrs</span><br></pre></td></tr></table></figure>

<h5 id="视图层：api-views-py-2"><a href="#视图层：api-views-py-2" class="headerlink" title="视图层：api/views.py"></a>视图层：api/views.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">V2Book</span><span class="params">(APIView)</span>:</span></span><br><span class="line">    <span class="comment"># 单查：有pk</span></span><br><span class="line">    <span class="comment"># 群查：无pk</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span><span class="params">(self, request, *args, **kwargs)</span>:</span></span><br><span class="line">        pk = kwargs.get(<span class="string">'pk'</span>)</span><br><span class="line">        <span class="keyword">if</span> pk:</span><br><span class="line">            <span class="keyword">try</span>:</span><br><span class="line">                book_obj = models.Book.objects.get(pk=pk, is_delete=<span class="literal">False</span>)</span><br><span class="line">                book_data = serializers.V2BookModelSerializer(book_obj).data</span><br><span class="line">            <span class="keyword">except</span>:</span><br><span class="line">                <span class="keyword">return</span> Response(&#123;</span><br><span class="line">                    <span class="string">'status'</span>: <span class="number">1</span>,</span><br><span class="line">                    <span class="string">'msg'</span>: <span class="string">'书籍不存在'</span></span><br><span class="line">                &#125;)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            book_query = models.Book.objects.filter(is_delete=<span class="literal">False</span>).all()</span><br><span class="line">            book_data = serializers.V2BookModelSerializer(book_query, many=<span class="literal">True</span>).data</span><br><span class="line">        <span class="keyword">return</span> Response(&#123;</span><br><span class="line">            <span class="string">'status'</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="string">'msg'</span>: <span class="string">'ok'</span>,</span><br><span class="line">            <span class="string">'results'</span>: book_data</span><br><span class="line">        &#125;)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 单增：传的数据是与model对应的字典</span></span><br><span class="line">    <span class="comment"># 群增：传的数据是 装多个 model对应字典 的列表</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">post</span><span class="params">(self, request, *args, **kwargs)</span>:</span></span><br><span class="line">        request_data = request.data</span><br><span class="line">        <span class="keyword">if</span> isinstance(request_data, dict):</span><br><span class="line">            many = <span class="literal">False</span></span><br><span class="line">        <span class="keyword">elif</span> isinstance(request_data, list):</span><br><span class="line">            many = <span class="literal">True</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">return</span> Response(&#123;</span><br><span class="line">                <span class="string">'status'</span>: <span class="number">1</span>,</span><br><span class="line">                <span class="string">'msg'</span>: <span class="string">'数据有误'</span>,</span><br><span class="line">            &#125;)</span><br><span class="line">        book_ser = serializers.V2BookModelSerializer(data=request_data, many=many)</span><br><span class="line">        <span class="comment"># 当校验失败，马上终止当前视图方法，抛异常返回给前台</span></span><br><span class="line">        book_ser.is_valid(raise_exception=<span class="literal">True</span>)</span><br><span class="line">        book_result = book_ser.save()</span><br><span class="line">        <span class="keyword">return</span> Response(&#123;</span><br><span class="line">            <span class="string">'status'</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="string">'msg'</span>: <span class="string">'ok'</span>,</span><br><span class="line">            <span class="string">'results'</span>: serializers.V2BookModelSerializer(book_result, many=many).data</span><br><span class="line">        &#125;)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 单删：有pk</span></span><br><span class="line">    <span class="comment"># 群删：有pks   |  &#123;"pks": [1, 2, 3]&#125;</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">delete</span><span class="params">(self, request, *args, **kwargs)</span>:</span></span><br><span class="line">        pk = kwargs.get(<span class="string">'pk'</span>)</span><br><span class="line">        <span class="keyword">if</span> pk:</span><br><span class="line">            pks = [pk]</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            pks = request.data.get(<span class="string">'pks'</span>)</span><br><span class="line">        <span class="keyword">if</span> models.Book.objects.filter(pk__in=pks, is_delete=<span class="literal">False</span>).update(is_delete=<span class="literal">True</span>):</span><br><span class="line">            <span class="keyword">return</span> Response(&#123;</span><br><span class="line">                <span class="string">'status'</span>: <span class="number">0</span>,</span><br><span class="line">                <span class="string">'msg'</span>: <span class="string">'删除成功'</span>,</span><br><span class="line">            &#125;)</span><br><span class="line">        <span class="keyword">return</span> Response(&#123;</span><br><span class="line">            <span class="string">'status'</span>: <span class="number">1</span>,</span><br><span class="line">            <span class="string">'msg'</span>: <span class="string">'删除失败'</span>,</span><br><span class="line">        &#125;)</span><br></pre></td></tr></table></figure>

<h5 id="路由层：api-urls-py-2"><a href="#路由层：api-urls-py-2" class="headerlink" title="路由层：api/urls.py"></a>路由层：api/urls.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">urlpatterns = [</span><br><span class="line">    url(<span class="string">r'^v2/books/$'</span>, views.V2Book.as_view()),</span><br><span class="line">    url(<span class="string">r'^v2/books/(?P&lt;pk&gt;.*)/$'</span>, views.V2Book.as_view()),</span><br><span class="line">]</span><br></pre></td></tr></table></figure>








      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/blog/2020/04/05/drf%E5%BA%8F%E5%88%97%E5%8C%96%E5%92%8C%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-redis操作" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/04/05/redis%E6%93%8D%E4%BD%9C/">redis操作</a>
    </h1>
  

        
        <a href="/blog/2020/04/05/redis%E6%93%8D%E4%BD%9C/" class="archive-article-date">
  	<time datetime="2020-04-05T07:51:33.956Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2020-04-05</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="redis数据库"><a href="#redis数据库" class="headerlink" title="redis数据库"></a>redis数据库</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1.安装redis与可视化操作工具</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2.在服务中管理redis服务器的开启关闭</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3.命令行简单使用redis：</span></span><br><span class="line">	-- redis-cli  <span class="comment"># 启动客户端</span></span><br><span class="line">    -- set key value  <span class="comment"># 设置值</span></span><br><span class="line">    -- get key  <span class="comment"># 取出值</span></span><br><span class="line">    </span><br><span class="line"><span class="comment"># 4.redis支持：字符串、字典、列表、集合、有序集合</span></span><br><span class="line"><span class="comment"># https://www.runoob.com/redis/redis-tutorial.html</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 5.特点：可持久化、单线程单进程并发</span></span><br></pre></td></tr></table></figure>

<h2 id="python使用redis"><a href="#python使用redis" class="headerlink" title="python使用redis"></a>python使用redis</h2><h5 id="依赖"><a href="#依赖" class="headerlink" title="依赖"></a>依赖</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;: pip3 install redis</span><br></pre></td></tr></table></figure>

<h5 id="直接使用"><a href="#直接使用" class="headerlink" title="直接使用"></a>直接使用</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> redis</span><br><span class="line">r = redis.Redis(host=<span class="string">'127.0.0.1'</span>, port=<span class="number">6379</span>)</span><br></pre></td></tr></table></figure>

<h5 id="连接池使用"><a href="#连接池使用" class="headerlink" title="连接池使用"></a>连接池使用</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> redis</span><br><span class="line">pool = redis.ConnectionPool(host=<span class="string">'127.0.0.1'</span>, port=<span class="number">6379</span>)</span><br><span class="line">r = redis.Redis(connection_pool=pool)</span><br></pre></td></tr></table></figure>

<h5 id="缓存使用：要额外安装-django-redis"><a href="#缓存使用：要额外安装-django-redis" class="headerlink" title="缓存使用：要额外安装 django-redis"></a>缓存使用：要额外安装 django-redis</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1.将缓存存储位置配置到redis中：settings.py</span></span><br><span class="line">CACHES = &#123;</span><br><span class="line">    <span class="string">"default"</span>: &#123;</span><br><span class="line">        <span class="string">"BACKEND"</span>: <span class="string">"django_redis.cache.RedisCache"</span>,</span><br><span class="line">        <span class="string">"LOCATION"</span>: <span class="string">"redis://127.0.0.1:6379"</span>,</span><br><span class="line">        <span class="string">"OPTIONS"</span>: &#123;</span><br><span class="line">            <span class="string">"CLIENT_CLASS"</span>: <span class="string">"django_redis.client.DefaultClient"</span>,</span><br><span class="line">            <span class="string">"CONNECTION_POOL_KWARGS"</span>: &#123;<span class="string">"max_connections"</span>: <span class="number">100</span>&#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2.操作cache模块直接操作缓存：views.py</span></span><br><span class="line"><span class="keyword">from</span> django.core.cache <span class="keyword">import</span> cache  <span class="comment"># 结合配置文件实现插拔式</span></span><br><span class="line"><span class="comment"># 存放token，可以直接设置过期时间</span></span><br><span class="line">cache.set(<span class="string">'token'</span>, <span class="string">'header.payload.signature'</span>, <span class="number">10</span>)</span><br><span class="line"><span class="comment"># 取出token</span></span><br><span class="line">token = cache.get(<span class="string">'token'</span>)</span><br></pre></td></tr></table></figure>


      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/blog/2020/04/05/redis%E6%93%8D%E4%BD%9C/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-4.celery" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/04/05/4.celery/">4.celery</a>
    </h1>
  

        
        <a href="/blog/2020/04/05/4.celery/" class="archive-article-date">
  	<time datetime="2020-04-05T07:51:10.462Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2020-04-05</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h1 id="Celery"><a href="#Celery" class="headerlink" title="Celery"></a>Celery</h1><h3 id="官方"><a href="#官方" class="headerlink" title="官方"></a>官方</h3><p>Celery 官网：<a href="http://www.celeryproject.org/" target="_blank" rel="noopener">http://www.celeryproject.org/</a></p>
<p>Celery 官方文档英文版：<a href="http://docs.celeryproject.org/en/latest/index.html" target="_blank" rel="noopener">http://docs.celeryproject.org/en/latest/index.html</a></p>
<p>Celery 官方文档中文版：<a href="http://docs.jinkan.org/docs/celery/" target="_blank" rel="noopener">http://docs.jinkan.org/docs/celery/</a></p>
<h2 id="Celery架构"><a href="#Celery架构" class="headerlink" title="Celery架构"></a>Celery架构</h2><p>Celery的架构由三部分组成，消息中间件（message broker）、任务执行单元（worker）和 任务执行结果存储（backend  -  task result store）组成。</p>
<h4 id="消息中间件"><a href="#消息中间件" class="headerlink" title="消息中间件"></a>消息中间件</h4><p>Celery本身不提供消息服务，但是可以方便的和第三方提供的消息中间件集成。包括，RabbitMQ, Redis等等</p>
<h4 id="任务执行单元"><a href="#任务执行单元" class="headerlink" title="任务执行单元"></a>任务执行单元</h4><p>Worker是Celery提供的任务执行的单元，worker并发的运行在分布式的系统节点中。</p>
<h4 id="任务结果存储"><a href="#任务结果存储" class="headerlink" title="任务结果存储"></a>任务结果存储</h4><p>Task result store用来存储Worker执行的任务的结果，Celery支持以不同方式存储任务的结果，包括AMQP, redis等</p>
<h2 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a>使用场景</h2><p>异步任务：将耗时操作任务提交给Celery去异步执行，比如发送短信/邮件、消息推送、音视频处理等等</p>
<p>定时任务：定时执行某件事情，比如每天数据统计</p>
<h2 id="Celery的安装配置"><a href="#Celery的安装配置" class="headerlink" title="Celery的安装配置"></a>Celery的安装配置</h2><p>pip install celery</p>
<p>消息中间件：RabbitMQ/Redis</p>
<p>app=celery.Celery(‘任务名’, broker=’xxx’, backend=’xxx’, include=[‘xxx’, ‘xxx’])</p>
<h2 id="Celery执行异步任务"><a href="#Celery执行异步任务" class="headerlink" title="Celery执行异步任务"></a>Celery执行异步任务</h2><h4 id="包架构封装"><a href="#包架构封装" class="headerlink" title="包架构封装"></a>包架构封装</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">project</span><br><span class="line">    ├── celery_task  	<span class="comment"># celery包</span></span><br><span class="line">    │   ├── __init__.py <span class="comment"># 包文件</span></span><br><span class="line">    │   ├── celery.py   <span class="comment"># celery连接和配置相关文件，且名字必须交celery.py</span></span><br><span class="line">    │   └── tasks.py    <span class="comment"># 所有任务函数</span></span><br><span class="line">    ├── add_task.py  	<span class="comment"># 添加任务</span></span><br><span class="line">    └── get_result.py   <span class="comment"># 获取结果</span></span><br></pre></td></tr></table></figure>



<h3 id="基本使用"><a href="#基本使用" class="headerlink" title="基本使用"></a>基本使用</h3><h5 id="celery-py"><a href="#celery-py" class="headerlink" title="celery.py"></a>celery.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1）创建app + 任务</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2）启动celery(app)服务：</span></span><br><span class="line"><span class="comment"># 非windows</span></span><br><span class="line"><span class="comment"># 命令：celery worker -A celery_task -l info</span></span><br><span class="line"><span class="comment"># windows：</span></span><br><span class="line"><span class="comment"># pip3 install eventlet</span></span><br><span class="line"><span class="comment"># celery worker -A celery_task -l info -P eventlet</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3）添加任务：手动添加，要自定义添加任务的脚本，右键执行脚本</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 4）获取结果：手动获取，要自定义获取任务的脚本，右键执行脚本</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> celery <span class="keyword">import</span> Celery</span><br><span class="line"></span><br><span class="line">broker = <span class="string">'redis://127.0.0.1:6379/1'</span></span><br><span class="line">backend = <span class="string">'redis://127.0.0.1:6379/2'</span></span><br><span class="line">app = Celery(broker=broker, backend=backend, include=[<span class="string">'celery_task.tasks'</span>])</span><br></pre></td></tr></table></figure>

<h5 id="tasks-py"><a href="#tasks-py" class="headerlink" title="tasks.py"></a>tasks.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> .celery <span class="keyword">import</span> app</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="meta">@app.task</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">add</span><span class="params">(n, m)</span>:</span></span><br><span class="line">    print(n)</span><br><span class="line">    print(m)</span><br><span class="line">    time.sleep(<span class="number">10</span>)</span><br><span class="line">    print(<span class="string">'n+m的结果：%s'</span> % (n + m))</span><br><span class="line">    <span class="keyword">return</span> n + m</span><br><span class="line"></span><br><span class="line"><span class="meta">@app.task</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">low</span><span class="params">(n, m)</span>:</span></span><br><span class="line">    print(n)</span><br><span class="line">    print(m)</span><br><span class="line">    print(<span class="string">'n-m的结果：%s'</span> % (n - m))</span><br><span class="line">    <span class="keyword">return</span> n - m</span><br></pre></td></tr></table></figure>

<h5 id="add-task-py"><a href="#add-task-py" class="headerlink" title="add_task.py"></a>add_task.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> celery_task <span class="keyword">import</span> tasks</span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加立即执行任务</span></span><br><span class="line">t1 = tasks.add.delay(<span class="number">10</span>, <span class="number">20</span>)</span><br><span class="line">t2 = tasks.low.delay(<span class="number">100</span>, <span class="number">50</span>)</span><br><span class="line">print(t1.id)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加延迟任务</span></span><br><span class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> datetime, timedelta</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">eta_second</span><span class="params">(second)</span>:</span></span><br><span class="line">    ctime = datetime.now()</span><br><span class="line">    utc_ctime = datetime.utcfromtimestamp(ctime.timestamp())</span><br><span class="line">    time_delay = timedelta(seconds=second)</span><br><span class="line">    <span class="keyword">return</span> utc_ctime + time_delay</span><br><span class="line"></span><br><span class="line">tasks.low.apply_async(args=(<span class="number">200</span>, <span class="number">50</span>), eta=eta_second(<span class="number">10</span>))</span><br></pre></td></tr></table></figure>

<h5 id="get-result-py"><a href="#get-result-py" class="headerlink" title="get_result.py"></a>get_result.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> celery_task.celery <span class="keyword">import</span> app</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> celery.result <span class="keyword">import</span> AsyncResult</span><br><span class="line"></span><br><span class="line">id = <span class="string">'21325a40-9d32-44b5-a701-9a31cc3c74b5'</span></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    <span class="keyword">async</span> = AsyncResult(id=id, app=app)</span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">async</span>.successful():</span><br><span class="line">        result = <span class="keyword">async</span>.get()</span><br><span class="line">        print(result)</span><br><span class="line">    <span class="keyword">elif</span> <span class="keyword">async</span>.failed():</span><br><span class="line">        print(<span class="string">'任务失败'</span>)</span><br><span class="line">    <span class="keyword">elif</span> <span class="keyword">async</span>.status == <span class="string">'PENDING'</span>:</span><br><span class="line">        print(<span class="string">'任务等待中被执行'</span>)</span><br><span class="line">    <span class="keyword">elif</span> <span class="keyword">async</span>.status == <span class="string">'RETRY'</span>:</span><br><span class="line">        print(<span class="string">'任务异常后正在重试'</span>)</span><br><span class="line">    <span class="keyword">elif</span> <span class="keyword">async</span>.status == <span class="string">'STARTED'</span>:</span><br><span class="line">        print(<span class="string">'任务已经开始被执行'</span>)</span><br></pre></td></tr></table></figure>



<h3 id="高级使用"><a href="#高级使用" class="headerlink" title="高级使用"></a>高级使用</h3><h5 id="celery-py-1"><a href="#celery-py-1" class="headerlink" title="celery.py"></a>celery.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1）创建app + 任务</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2）启动celery(app)服务：</span></span><br><span class="line"><span class="comment"># 非windows</span></span><br><span class="line"><span class="comment"># 命令：celery worker -A celery_task -l info</span></span><br><span class="line"><span class="comment"># windows：</span></span><br><span class="line"><span class="comment"># pip3 install eventlet</span></span><br><span class="line"><span class="comment"># celery worker -A celery_task -l info -P eventlet</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3）添加任务：自动添加任务，所以要启动一个添加任务的服务</span></span><br><span class="line"><span class="comment"># 命令：celery beat -A celery_task -l info</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 4）获取结果</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> celery <span class="keyword">import</span> Celery</span><br><span class="line"></span><br><span class="line">broker = <span class="string">'redis://127.0.0.1:6379/1'</span></span><br><span class="line">backend = <span class="string">'redis://127.0.0.1:6379/2'</span></span><br><span class="line">app = Celery(broker=broker, backend=backend, include=[<span class="string">'celery_task.tasks'</span>])</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 时区</span></span><br><span class="line">app.conf.timezone = <span class="string">'Asia/Shanghai'</span></span><br><span class="line"><span class="comment"># 是否使用UTC</span></span><br><span class="line">app.conf.enable_utc = <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 任务的定时配置</span></span><br><span class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> timedelta</span><br><span class="line"><span class="keyword">from</span> celery.schedules <span class="keyword">import</span> crontab</span><br><span class="line">app.conf.beat_schedule = &#123;</span><br><span class="line">    <span class="string">'low-task'</span>: &#123;</span><br><span class="line">        <span class="string">'task'</span>: <span class="string">'celery_task.tasks.low'</span>,</span><br><span class="line">        <span class="string">'schedule'</span>: timedelta(seconds=<span class="number">3</span>),</span><br><span class="line">        <span class="comment"># 'schedule': crontab(hour=8, day_of_week=1),  # 每周一早八点</span></span><br><span class="line">        <span class="string">'args'</span>: (<span class="number">300</span>, <span class="number">150</span>),</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="tasks-py-1"><a href="#tasks-py-1" class="headerlink" title="tasks.py"></a>tasks.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> .celery <span class="keyword">import</span> app</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="meta">@app.task</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">add</span><span class="params">(n, m)</span>:</span></span><br><span class="line">    print(n)</span><br><span class="line">    print(m)</span><br><span class="line">    time.sleep(<span class="number">10</span>)</span><br><span class="line">    print(<span class="string">'n+m的结果：%s'</span> % (n + m))</span><br><span class="line">    <span class="keyword">return</span> n + m</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@app.task</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">low</span><span class="params">(n, m)</span>:</span></span><br><span class="line">    print(n)</span><br><span class="line">    print(m)</span><br><span class="line">    print(<span class="string">'n-m的结果：%s'</span> % (n - m))</span><br><span class="line">    <span class="keyword">return</span> n - m</span><br></pre></td></tr></table></figure>

<h5 id="get-result-py-1"><a href="#get-result-py-1" class="headerlink" title="get_result.py"></a>get_result.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> celery_task.celery <span class="keyword">import</span> app</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> celery.result <span class="keyword">import</span> AsyncResult</span><br><span class="line"></span><br><span class="line">id = <span class="string">'21325a40-9d32-44b5-a701-9a31cc3c74b5'</span></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    <span class="keyword">async</span> = AsyncResult(id=id, app=app)</span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">async</span>.successful():</span><br><span class="line">        result = <span class="keyword">async</span>.get()</span><br><span class="line">        print(result)</span><br><span class="line">    <span class="keyword">elif</span> <span class="keyword">async</span>.failed():</span><br><span class="line">        print(<span class="string">'任务失败'</span>)</span><br><span class="line">    <span class="keyword">elif</span> <span class="keyword">async</span>.status == <span class="string">'PENDING'</span>:</span><br><span class="line">        print(<span class="string">'任务等待中被执行'</span>)</span><br><span class="line">    <span class="keyword">elif</span> <span class="keyword">async</span>.status == <span class="string">'RETRY'</span>:</span><br><span class="line">        print(<span class="string">'任务异常后正在重试'</span>)</span><br><span class="line">    <span class="keyword">elif</span> <span class="keyword">async</span>.status == <span class="string">'STARTED'</span>:</span><br><span class="line">        print(<span class="string">'任务已经开始被执行'</span>)</span><br></pre></td></tr></table></figure>



<h3 id="django中使用"><a href="#django中使用" class="headerlink" title="django中使用"></a>django中使用</h3><h5 id="celery-py-2"><a href="#celery-py-2" class="headerlink" title="celery.py"></a>celery.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 重点：要将 项目名.settings 所占的文件夹添加到环境变量</span></span><br><span class="line"><span class="comment"># import sys</span></span><br><span class="line"><span class="comment"># sys.path.append(r'项目绝对路径')</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 开启django支持</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line">os.environ.setdefault(<span class="string">'DJANGO_SETTINGS_MODULE'</span>, <span class="string">'项目名.settings'</span>)</span><br><span class="line"><span class="keyword">import</span> django</span><br><span class="line">django.setup()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 1）创建app + 任务</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2）启动celery(app)服务：</span></span><br><span class="line"><span class="comment"># 非windows</span></span><br><span class="line"><span class="comment"># 命令：celery worker -A celery_task -l info</span></span><br><span class="line"><span class="comment"># windows：</span></span><br><span class="line"><span class="comment"># pip3 install eventlet</span></span><br><span class="line"><span class="comment"># celery worker -A celery_task -l info -P eventlet</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3）添加任务：自动添加任务，所以要启动一个添加任务的服务</span></span><br><span class="line"><span class="comment"># 命令：celery beat -A celery_task -l info</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 4）获取结果</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> celery <span class="keyword">import</span> Celery</span><br><span class="line"></span><br><span class="line">broker = <span class="string">'redis://127.0.0.1:6379/1'</span></span><br><span class="line">backend = <span class="string">'redis://127.0.0.1:6379/2'</span></span><br><span class="line">app = Celery(broker=broker, backend=backend, include=[<span class="string">'celery_task.tasks'</span>])</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 时区</span></span><br><span class="line">app.conf.timezone = <span class="string">'Asia/Shanghai'</span></span><br><span class="line"><span class="comment"># 是否使用UTC</span></span><br><span class="line">app.conf.enable_utc = <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 任务的定时配置</span></span><br><span class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> timedelta</span><br><span class="line"><span class="keyword">from</span> celery.schedules <span class="keyword">import</span> crontab</span><br><span class="line">app.conf.beat_schedule = &#123;</span><br><span class="line">    <span class="string">'django-task'</span>: &#123;</span><br><span class="line">        <span class="string">'task'</span>: <span class="string">'celery_task.tasks.test_django_celery'</span>,</span><br><span class="line">        <span class="string">'schedule'</span>: timedelta(seconds=<span class="number">3</span>),</span><br><span class="line">        <span class="string">'args'</span>: (),</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="tasks-py-2"><a href="#tasks-py-2" class="headerlink" title="tasks.py"></a>tasks.py</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> .celery <span class="keyword">import</span> app</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> home.models <span class="keyword">import</span> Banner</span><br><span class="line"><span class="keyword">from</span> settings.const <span class="keyword">import</span> BANNER_COUNT  <span class="comment"># 轮播图最大显示条数</span></span><br><span class="line"><span class="keyword">from</span> home.serializers <span class="keyword">import</span> BannerModelSerializer</span><br><span class="line"><span class="keyword">from</span> django.core.cache <span class="keyword">import</span> cache</span><br><span class="line"><span class="meta">@app.task</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">update_banner_list</span><span class="params">()</span>:</span></span><br><span class="line">    <span class="comment"># 获取最新内容</span></span><br><span class="line">    banner_query = Banner.objects.filter(is_delete=<span class="literal">False</span>, is_show=<span class="literal">True</span>).order_by(<span class="string">'-orders'</span>)[:BANNER_COUNT]</span><br><span class="line">    <span class="comment"># 序列化</span></span><br><span class="line">    banner_data = BannerModelSerializer(banner_query, many=<span class="literal">True</span>).data</span><br><span class="line">    <span class="keyword">for</span> banner <span class="keyword">in</span> banner_data:</span><br><span class="line">        banner[<span class="string">'image'</span>] = <span class="string">'http://127.0.0.1:8000'</span> + banner[<span class="string">'image'</span>]</span><br><span class="line">    <span class="comment"># 更新缓存</span></span><br><span class="line">    cache.set(<span class="string">'banner_list'</span>, banner_data)</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">True</span></span><br></pre></td></tr></table></figure>
















      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/blog/2020/04/05/4.celery/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-drf相关模块学习" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/04/05/drf%E7%9B%B8%E5%85%B3%E6%A8%A1%E5%9D%97%E5%AD%A6%E4%B9%A0/">drf相关模块学习</a>
    </h1>
  

        
        <a href="/blog/2020/04/05/drf%E7%9B%B8%E5%85%B3%E6%A8%A1%E5%9D%97%E5%AD%A6%E4%B9%A0/" class="archive-article-date">
  	<time datetime="2020-04-05T07:17:04.788Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2020-04-05</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="解析模块"><a href="#解析模块" class="headerlink" title="解析模块"></a>解析模块</h2><h5 id="为什么要配置解析模块"><a href="#为什么要配置解析模块" class="headerlink" title="为什么要配置解析模块"></a>为什么要配置解析模块</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">1）drf给我们通过了多种解析数据包方式的解析类</span></span><br><span class="line"><span class="string">2）我们可以通过配置来控制前台提交的哪些格式的数据后台在解析，哪些数据不解析</span></span><br><span class="line"><span class="string">3）全局配置就是针对每一个视图类，局部配置就是针对指定的视图来，让它们可以按照配置规则选择性解析数据</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></table></figure>

<h5 id="源码入口"><a href="#源码入口" class="headerlink" title="源码入口"></a>源码入口</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># APIView类的dispatch方法中</span></span><br><span class="line">request = self.initialize_request(request, *args, **kwargs)  <span class="comment"># 点进去</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取解析类</span></span><br><span class="line">parsers=self.get_parsers(),  <span class="comment"># 点进去</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 去类属性(局部配置) 或 配置文件(全局配置) 拿 parser_classes</span></span><br><span class="line"><span class="keyword">return</span> [parser() <span class="keyword">for</span> parser <span class="keyword">in</span> self.parser_classes]</span><br></pre></td></tr></table></figure>

<h5 id="全局配置：项目settings-py文件"><a href="#全局配置：项目settings-py文件" class="headerlink" title="全局配置：项目settings.py文件"></a>全局配置：项目settings.py文件</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">REST_FRAMEWORK = &#123;</span><br><span class="line">    <span class="comment"># 全局解析类配置</span></span><br><span class="line">    <span class="string">'DEFAULT_PARSER_CLASSES'</span>: [</span><br><span class="line">        <span class="string">'rest_framework.parsers.JSONParser'</span>,  <span class="comment"># json数据包</span></span><br><span class="line">        <span class="string">'rest_framework.parsers.FormParser'</span>,  <span class="comment"># urlencoding数据包</span></span><br><span class="line">        <span class="string">'rest_framework.parsers.MultiPartParser'</span>  <span class="comment"># form-date数据包</span></span><br><span class="line">    ],</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="局部配置：应用views-py的具体视图类"><a href="#局部配置：应用views-py的具体视图类" class="headerlink" title="局部配置：应用views.py的具体视图类"></a>局部配置：应用views.py的具体视图类</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> rest_framework.parsers <span class="keyword">import</span> JSONParser</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Book</span><span class="params">(APIView)</span>:</span></span><br><span class="line">    <span class="comment"># 局部解析类配置，只要json类型的数据包才能被解析</span></span><br><span class="line">    parser_classes = [JSONParser]</span><br><span class="line">    <span class="keyword">pass</span></span><br></pre></td></tr></table></figure>





<h2 id="异常模块"><a href="#异常模块" class="headerlink" title="异常模块"></a>异常模块</h2><h5 id="为什么要自定义异常模块"><a href="#为什么要自定义异常模块" class="headerlink" title="为什么要自定义异常模块"></a>为什么要自定义异常模块</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">1）所有经过drf的APIView视图类产生的异常，都可以提供异常处理方案</span></span><br><span class="line"><span class="string">2）drf默认提供了异常处理方案(rest_framework.views.exception_handler)，但是处理范围有限</span></span><br><span class="line"><span class="string">3）drf提供的处理方案两种，处理了返回异常现象，没处理返回None(后续就是服务器抛异常给前台)</span></span><br><span class="line"><span class="string">4）自定义异常的目的就是解决drf没有处理的异常，让前台得到合理的异常信息返回，后台记录异常具体信息</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></table></figure>

<h5 id="源码分析"><a href="#源码分析" class="headerlink" title="源码分析"></a>源码分析</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 异常模块：APIView类的dispatch方法中</span></span><br><span class="line">response = self.handle_exception(exc)  <span class="comment"># 点进去</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取处理异常的句柄(方法)</span></span><br><span class="line"><span class="comment"># 一层层看源码，走的是配置文件，拿到的是rest_framework.views的exception_handler</span></span><br><span class="line"><span class="comment"># 自定义：直接写exception_handler函数，在自己的配置文件配置EXCEPTION_HANDLER指向自己的</span></span><br><span class="line">exception_handler = self.get_exception_handler()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 异常处理的结果</span></span><br><span class="line"><span class="comment"># 自定义异常就是提供exception_handler异常处理函数，处理的目的就是让response一定有值</span></span><br><span class="line">response = exception_handler(exc, context)</span><br></pre></td></tr></table></figure>

<h5 id="如何使用：自定义exception-handler函数如何书写实现体"><a href="#如何使用：自定义exception-handler函数如何书写实现体" class="headerlink" title="如何使用：自定义exception_handler函数如何书写实现体"></a>如何使用：自定义exception_handler函数如何书写实现体</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 修改自己的配置文件setting.py</span></span><br><span class="line">REST_FRAMEWORK = &#123;</span><br><span class="line">    <span class="comment"># 全局配置异常模块</span></span><br><span class="line">    <span class="string">'EXCEPTION_HANDLER'</span>: <span class="string">'api.exception.exception_handler'</span>,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1）先将异常处理交给rest_framework.views的exception_handler去处理</span></span><br><span class="line"><span class="comment"># 2）判断处理的结果(返回值)response，有值代表drf已经处理了，None代表需要自己处理</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 自定义异常处理文件exception，在文件中书写exception_handler函数</span></span><br><span class="line"><span class="keyword">from</span> rest_framework.views <span class="keyword">import</span> exception_handler <span class="keyword">as</span> drf_exception_handler</span><br><span class="line"><span class="keyword">from</span> rest_framework.views <span class="keyword">import</span> Response</span><br><span class="line"><span class="keyword">from</span> rest_framework <span class="keyword">import</span> status</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">exception_handler</span><span class="params">(exc, context)</span>:</span></span><br><span class="line">    <span class="comment"># drf的exception_handler做基础处理</span></span><br><span class="line">    response = drf_exception_handler(exc, context)</span><br><span class="line">    <span class="comment"># 为空，自定义二次处理</span></span><br><span class="line">    <span class="keyword">if</span> response <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">        <span class="comment"># print(exc)</span></span><br><span class="line">        <span class="comment"># print(context)</span></span><br><span class="line">        print(<span class="string">'%s - %s - %s'</span> % (context[<span class="string">'view'</span>], context[<span class="string">'request'</span>].method, exc))</span><br><span class="line">        <span class="keyword">return</span> Response(&#123;</span><br><span class="line">            <span class="string">'detail'</span>: <span class="string">'服务器错误'</span></span><br><span class="line">        &#125;, status=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=<span class="literal">True</span>)</span><br><span class="line">    <span class="keyword">return</span> response</span><br></pre></td></tr></table></figure>





<h2 id="响应模块"><a href="#响应模块" class="headerlink" title="响应模块"></a>响应模块</h2><h5 id="响应类构造器：rest-framework-response-Response"><a href="#响应类构造器：rest-framework-response-Response" class="headerlink" title="响应类构造器：rest_framework.response.Response"></a>响应类构造器：rest_framework.response.Response</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, data=None, status=None,</span></span></span><br><span class="line"><span class="function"><span class="params">                 template_name=None, headers=None,</span></span></span><br><span class="line"><span class="function"><span class="params">                 exception=False, content_type=None)</span>:</span></span><br><span class="line">     <span class="string">"""</span></span><br><span class="line"><span class="string">        :param data: 响应数据</span></span><br><span class="line"><span class="string">        :param status: http响应状态码</span></span><br><span class="line"><span class="string">        :param template_name: drf也可以渲染页面，渲染的页面模板地址（不用了解）</span></span><br><span class="line"><span class="string">        :param headers: 响应头</span></span><br><span class="line"><span class="string">        :param exception: 是否异常了</span></span><br><span class="line"><span class="string">        :param content_type: 响应的数据格式（一般不用处理，响应头中带了，且默认是json）</span></span><br><span class="line"><span class="string">    """</span></span><br><span class="line">    <span class="keyword">pass</span></span><br></pre></td></tr></table></figure>

<h5 id="使用：常规实例化响应对象"><a href="#使用：常规实例化响应对象" class="headerlink" title="使用：常规实例化响应对象"></a>使用：常规实例化响应对象</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># status就是解释一堆 数字 网络状态码的模块</span></span><br><span class="line"><span class="keyword">from</span> rest_framework <span class="keyword">import</span> status就是解释一堆 数字 网络状态码的模块</span><br><span class="line"><span class="comment"># 一般情况下只需要返回数据，status和headers都有默认值</span></span><br><span class="line"><span class="keyword">return</span> Response(data=&#123;数据&#125;, status=status.HTTP_200_OK, headers=&#123;设置的响应头&#125;)</span><br></pre></td></tr></table></figure>





<h2 id="序列化组件："><a href="#序列化组件：" class="headerlink" title="序列化组件："></a>序列化组件：</h2><h5 id="知识点：Serializer-偏底层-、ModelSerializer-重点-、ListModelSerializer-辅助群改"><a href="#知识点：Serializer-偏底层-、ModelSerializer-重点-、ListModelSerializer-辅助群改" class="headerlink" title="知识点：Serializer(偏底层)、ModelSerializer(重点)、ListModelSerializer(辅助群改)"></a>知识点：Serializer(偏底层)、ModelSerializer(重点)、ListModelSerializer(辅助群改)</h5><h2 id="Serializer"><a href="#Serializer" class="headerlink" title="Serializer"></a>Serializer</h2><h4 id="序列化准备："><a href="#序列化准备：" class="headerlink" title="序列化准备："></a>序列化准备：</h4><ul>
<li>模型层：models.py</li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span><span class="params">(models.Model)</span>:</span></span><br><span class="line">    SEX_CHOICES = [</span><br><span class="line">        [<span class="number">0</span>, <span class="string">'男'</span>],</span><br><span class="line">        [<span class="number">1</span>, <span class="string">'女'</span>],</span><br><span class="line">    ]</span><br><span class="line">    name = models.CharField(max_length=<span class="number">64</span>)</span><br><span class="line">    pwd = models.CharField(max_length=<span class="number">32</span>)</span><br><span class="line">    phone = models.CharField(max_length=<span class="number">11</span>, null=<span class="literal">True</span>, default=<span class="literal">None</span>)</span><br><span class="line">    sex = models.IntegerField(choices=SEX_CHOICES, default=<span class="number">0</span>)</span><br><span class="line">    icon = models.ImageField(upload_to=<span class="string">'icon'</span>, default=<span class="string">'icon/default.jpg'</span>)</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line">        db_table = <span class="string">'old_boy_user'</span></span><br><span class="line">        verbose_name = <span class="string">'用户'</span></span><br><span class="line">        verbose_name_plural = verbose_name</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__str__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> <span class="string">'%s'</span> % self.name</span><br></pre></td></tr></table></figure>

<ul>
<li>后台管理层：admin.py</li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.contrib <span class="keyword">import</span> admin</span><br><span class="line"><span class="keyword">from</span> . <span class="keyword">import</span> models</span><br><span class="line"></span><br><span class="line">admin.site.register(models.User)</span><br></pre></td></tr></table></figure>

<ul>
<li>配置层：settings.py</li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 注册rest_framework</span></span><br><span class="line">INSTALLED_APPS = [</span><br><span class="line">    <span class="comment"># ...</span></span><br><span class="line">    <span class="string">'rest_framework'</span>,</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置数据库</span></span><br><span class="line">DATABASES = &#123;</span><br><span class="line">    <span class="string">'default'</span>: &#123;</span><br><span class="line">        <span class="string">'ENGINE'</span>: <span class="string">'django.db.backends.mysql'</span>,</span><br><span class="line">        <span class="string">'NAME'</span>: <span class="string">'day70'</span>,</span><br><span class="line">        <span class="string">'USER'</span>: <span class="string">'root'</span>,</span><br><span class="line">        <span class="string">'PASSWORD'</span>: <span class="string">'123'</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># media资源</span></span><br><span class="line">MEDIA_URL = <span class="string">'/media/'</span>  <span class="comment"># 后期高级序列化类与视图类，会使用该配置</span></span><br><span class="line">MEDIA_ROOT = os.path.join(BASE_DIR, <span class="string">'media'</span>)  <span class="comment"># media资源路径</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 国际化配置</span></span><br><span class="line">LANGUAGE_CODE = <span class="string">'zh-hans'</span></span><br><span class="line">TIME_ZONE = <span class="string">'Asia/Shanghai'</span></span><br><span class="line">USE_I18N = <span class="literal">True</span></span><br><span class="line">USE_L10N = <span class="literal">True</span></span><br><span class="line">USE_TZ = <span class="literal">False</span></span><br></pre></td></tr></table></figure>

<ul>
<li>主路由：项目下urls.py</li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">urlpatterns = [</span><br><span class="line">    <span class="comment"># ...</span></span><br><span class="line">    url(<span class="string">r'^api/'</span>, include(<span class="string">'api.urls'</span>)),</span><br><span class="line"></span><br><span class="line">    url(<span class="string">r'^media/(?P&lt;path&gt;.*)'</span>, serve, &#123;<span class="string">'document_root'</span>: settings.MEDIA_ROOT&#125;),</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<ul>
<li>子路由：应用下urls.py</li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">urlpatterns = [</span><br><span class="line">    url(<span class="string">r'^users/$'</span>, views.User.as_view()),</span><br><span class="line">    url(<span class="string">r'^users/(?P&lt;pk&gt;.*)/$'</span>, views.User.as_view()),</span><br><span class="line">]</span><br></pre></td></tr></table></figure>



<h4 id="序列化使用"><a href="#序列化使用" class="headerlink" title="序列化使用"></a>序列化使用</h4><ul>
<li>序列化层：api/serializers.py</li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">1）设置需要返回给前台 那些model类有对应的字段，不需要返回的就不用设置了</span></span><br><span class="line"><span class="string">2）设置方法字段，字段名可以随意，字段值有 get_字段名 提供，来完成一些需要处理在返回的数据</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></table></figure>

<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 序列化组件 - 为每一个model类通过一套序列化工具类</span></span><br><span class="line"><span class="comment"># 序列化组件的工作方式与django froms组件非常相似</span></span><br><span class="line"><span class="keyword">from</span> rest_framework <span class="keyword">import</span> serializers, exceptions</span><br><span class="line"><span class="keyword">from</span> django.conf <span class="keyword">import</span> settings</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> . <span class="keyword">import</span> models</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserSerializer</span><span class="params">(serializers.Serializer)</span>:</span></span><br><span class="line">    name = serializers.CharField()</span><br><span class="line">    phone = serializers.CharField()</span><br><span class="line">    <span class="comment"># 序列化提供给前台的字段个数由后台决定，可以少提供，</span></span><br><span class="line">    <span class="comment"># 但是提供的数据库对应的字段，名字一定要与数据库字段相同</span></span><br><span class="line">    <span class="comment"># sex = serializers.IntegerField()</span></span><br><span class="line">    <span class="comment"># icon = serializers.ImageField()</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 自定义序列化属性</span></span><br><span class="line">    <span class="comment"># 属性名随意，值由固定的命名规范方法提供:</span></span><br><span class="line">    <span class="comment">#       get_属性名(self, 参与序列化的model对象)</span></span><br><span class="line">    <span class="comment">#       返回值就是自定义序列化属性的值</span></span><br><span class="line">    gender = serializers.SerializerMethodField()</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_gender</span><span class="params">(self, obj)</span>:</span></span><br><span class="line">        <span class="comment"># choice类型的解释型值 get_字段_display() 来访问</span></span><br><span class="line">        <span class="keyword">return</span> obj.get_sex_display()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    icon = serializers.SerializerMethodField()</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_icon</span><span class="params">(self, obj)</span>:</span></span><br><span class="line">        <span class="comment"># settings.MEDIA_URL: 自己配置的 /media/，给后面高级序列化与视图类准备的</span></span><br><span class="line">        <span class="comment"># obj.icon不能直接作为数据返回，因为内容虽然是字符串，但是类型是ImageFieldFile类型</span></span><br><span class="line">        <span class="keyword">return</span> <span class="string">'%s%s%s'</span> % (<span class="string">r'http://127.0.0.1:8000'</span>, settings.MEDIA_URL, str(obj.icon))</span><br></pre></td></tr></table></figure>

<ul>
<li>视图层</li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">1）从数据库中将要序列化给前台的model对象，或是对个model对象查询出来</span></span><br><span class="line"><span class="string">	user_obj = models.User.objects.get(pk=pk) 或者</span></span><br><span class="line"><span class="string">	user_obj_list = models.User.objects.all()</span></span><br><span class="line"><span class="string">2）将对象交给序列化处理，产生序列化对象，如果序列化的是多个数据，要设置many=True</span></span><br><span class="line"><span class="string">	user_ser = serializers.UserSerializer(user_obj) 或者</span></span><br><span class="line"><span class="string">	user_ser = serializers.UserSerializer(user_obj_list, many=True)</span></span><br><span class="line"><span class="string">3）序列化 对象.data 就是可以返回给前台的序列化数据</span></span><br><span class="line"><span class="string">	return Response(&#123;</span></span><br><span class="line"><span class="string">        'status': 0,</span></span><br><span class="line"><span class="string">        'msg': 0,</span></span><br><span class="line"><span class="string">        'results': user_ser.data</span></span><br><span class="line"><span class="string">    &#125;)</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></table></figure>

<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span><span class="params">(APIView)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span><span class="params">(self, request, *args, **kwargs)</span>:</span></span><br><span class="line">        pk = kwargs.get(<span class="string">'pk'</span>)</span><br><span class="line">        <span class="keyword">if</span> pk:</span><br><span class="line">            <span class="keyword">try</span>:</span><br><span class="line">                <span class="comment"># 用户对象不能直接作为数据返回给前台</span></span><br><span class="line">                user_obj = models.User.objects.get(pk=pk)</span><br><span class="line">                <span class="comment"># 序列化一下用户对象</span></span><br><span class="line">                user_ser = serializers.UserSerializer(user_obj)</span><br><span class="line">                <span class="comment"># print(user_ser, type(user_ser))</span></span><br><span class="line">                <span class="keyword">return</span> Response(&#123;</span><br><span class="line">                    <span class="string">'status'</span>: <span class="number">0</span>,</span><br><span class="line">                    <span class="string">'msg'</span>: <span class="number">0</span>,</span><br><span class="line">                    <span class="string">'results'</span>: user_ser.data</span><br><span class="line">                &#125;)</span><br><span class="line">            <span class="keyword">except</span>:</span><br><span class="line">                <span class="keyword">return</span> Response(&#123;</span><br><span class="line">                    <span class="string">'status'</span>: <span class="number">2</span>,</span><br><span class="line">                    <span class="string">'msg'</span>: <span class="string">'用户不存在'</span>,</span><br><span class="line">                &#125;)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="comment"># 用户对象列表(queryset)不能直接作为数据返回给前台</span></span><br><span class="line">            user_obj_list = models.User.objects.all()</span><br><span class="line">            <span class="comment"># 序列化一下用户对象</span></span><br><span class="line">            user_ser_data = serializers.UserSerializer(user_obj_list, many=<span class="literal">True</span>).data</span><br><span class="line">            <span class="keyword">return</span> Response(&#123;</span><br><span class="line">                <span class="string">'status'</span>: <span class="number">0</span>,</span><br><span class="line">                <span class="string">'msg'</span>: <span class="number">0</span>,</span><br><span class="line">                <span class="string">'results'</span>: user_ser_data</span><br><span class="line">            &#125;)</span><br></pre></td></tr></table></figure>





<h4 id="反序列化使用"><a href="#反序列化使用" class="headerlink" title="反序列化使用"></a>反序列化使用</h4><ul>
<li>反序列层：api/serializers.py</li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">1）设置必填与选填序列化字段，设置校验规则</span></span><br><span class="line"><span class="string">2）为需要额外校验的字段提供局部钩子函数，如果该字段不入库，且不参与全局钩子校验，可以将值取出校验</span></span><br><span class="line"><span class="string">3）为有联合关系的字段们提供全局钩子函数，如果某些字段不入库，可以将值取出校验</span></span><br><span class="line"><span class="string">4）重写create方法，完成校验通过的数据入库工作，得到新增的对象</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></table></figure>

<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserDeserializer</span><span class="params">(serializers.Serializer)</span>:</span></span><br><span class="line">    <span class="comment"># 1) 哪些自动必须反序列化</span></span><br><span class="line">    <span class="comment"># 2) 字段都有哪些安全校验</span></span><br><span class="line">    <span class="comment"># 3) 哪些字段需要额外提供校验</span></span><br><span class="line">    <span class="comment"># 4) 哪些字段间存在联合校验</span></span><br><span class="line">    <span class="comment"># 注：反序列化字段都是用来入库的，不会出现自定义方法属性，会出现可以设置校验规则的自定义属性(re_pwd)</span></span><br><span class="line">    name = serializers.CharField(</span><br><span class="line">        max_length=<span class="number">64</span>,</span><br><span class="line">        min_length=<span class="number">3</span>,</span><br><span class="line">        error_messages=&#123;</span><br><span class="line">            <span class="string">'max_length'</span>: <span class="string">'太长'</span>,</span><br><span class="line">            <span class="string">'min_length'</span>: <span class="string">'太短'</span></span><br><span class="line">        &#125;</span><br><span class="line">    )</span><br><span class="line">    pwd = serializers.CharField()</span><br><span class="line">    phone = serializers.CharField(required=<span class="literal">False</span>)</span><br><span class="line">    sex = serializers.IntegerField(required=<span class="literal">False</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 自定义有校验规则的反序列化字段</span></span><br><span class="line">    re_pwd = serializers.CharField(required=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 小结：</span></span><br><span class="line">    <span class="comment"># name，pwd，re_pwd为必填字段</span></span><br><span class="line">    <span class="comment"># phone，sex为选填字段</span></span><br><span class="line">    <span class="comment"># 五个字段都必须提供完成的校验规则</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 局部钩子：validate_要校验的字段名(self, 当前要校验字段的值)</span></span><br><span class="line">    <span class="comment"># 校验规则：校验通过返回原值，校验失败，抛出异常</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">validate_name</span><span class="params">(self, value)</span>:</span></span><br><span class="line">        <span class="keyword">if</span> <span class="string">'g'</span> <span class="keyword">in</span> value.lower():  <span class="comment"># 名字中不能出现g</span></span><br><span class="line">            <span class="keyword">raise</span> exceptions.ValidationError(<span class="string">'名字非法，是个鸡贼！'</span>)</span><br><span class="line">        <span class="keyword">return</span> value</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 全局钩子：validate(self, 系统与局部钩子校验通过的所有数据)</span></span><br><span class="line">    <span class="comment"># 校验规则：校验通过返回原值，校验失败，抛出异常</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">validate</span><span class="params">(self, attrs)</span>:</span></span><br><span class="line">        pwd = attrs.get(<span class="string">'pwd'</span>)</span><br><span class="line">        re_pwd = attrs.pop(<span class="string">'re_pwd'</span>)</span><br><span class="line">        <span class="keyword">if</span> pwd != re_pwd:</span><br><span class="line">            <span class="keyword">raise</span> exceptions.ValidationError(&#123;<span class="string">'pwd&amp;re_pwd'</span>: <span class="string">'两次密码不一致'</span>&#125;)</span><br><span class="line">        <span class="keyword">return</span> attrs</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 要完成新增，需要自己重写 create 方法</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">create</span><span class="params">(self, validated_data)</span>:</span></span><br><span class="line">        <span class="comment"># 尽量在所有校验规则完毕之后，数据可以直接入库</span></span><br><span class="line">        <span class="keyword">return</span> models.User.objects.create(**validated_data)</span><br></pre></td></tr></table></figure>

<ul>
<li>视图层</li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">1）book_ser = serializers.UserDeserializer(data=request_data)  # 数据必须赋值data</span></span><br><span class="line"><span class="string">2）book_ser.is_valid()  # 结果为 通过 | 不通过</span></span><br><span class="line"><span class="string">3）不通过返回 book_ser.errors 给前台，通过 book_ser.save() 得到新增的对象，再正常返回</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></table></figure>

<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span><span class="params">(APIView)</span>:</span></span><br><span class="line">    <span class="comment"># 只考虑单增</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">post</span><span class="params">(self, request, *args, **kwargs)</span>:</span></span><br><span class="line">        <span class="comment"># 请求数据</span></span><br><span class="line">        request_data = request.data</span><br><span class="line">        <span class="comment"># 数据是否合法（增加对象需要一个字典数据）</span></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> isinstance(request_data, dict) <span class="keyword">or</span> request_data == &#123;&#125;:</span><br><span class="line">            <span class="keyword">return</span> Response(&#123;</span><br><span class="line">                <span class="string">'status'</span>: <span class="number">1</span>,</span><br><span class="line">                <span class="string">'msg'</span>: <span class="string">'数据有误'</span>,</span><br><span class="line">            &#125;)</span><br><span class="line">        <span class="comment"># 数据类型合法，但数据内容不一定合法，需要校验数据，校验(参与反序列化)的数据需要赋值给data</span></span><br><span class="line">        book_ser = serializers.UserDeserializer(data=request_data)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 序列化对象调用is_valid()完成校验，校验失败的失败信息都会被存储在 序列化对象.errors</span></span><br><span class="line">        <span class="keyword">if</span> book_ser.is_valid():</span><br><span class="line">            <span class="comment"># 校验通过，完成新增</span></span><br><span class="line">            book_obj = book_ser.save()</span><br><span class="line">            <span class="keyword">return</span> Response(&#123;</span><br><span class="line">                <span class="string">'status'</span>: <span class="number">0</span>,</span><br><span class="line">                <span class="string">'msg'</span>: <span class="string">'ok'</span>,</span><br><span class="line">                <span class="string">'results'</span>: serializers.UserSerializer(book_obj).data</span><br><span class="line">            &#125;)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="comment"># 校验失败</span></span><br><span class="line">            <span class="keyword">return</span> Response(&#123;</span><br><span class="line">                <span class="string">'status'</span>: <span class="number">1</span>,</span><br><span class="line">                <span class="string">'msg'</span>: book_ser.errors,</span><br><span class="line">            &#125;)</span><br></pre></td></tr></table></figure>
















      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/blog/2020/04/05/drf%E7%9B%B8%E5%85%B3%E6%A8%A1%E5%9D%97%E5%AD%A6%E4%B9%A0/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-数据库学习" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/04/05/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AD%A6%E4%B9%A0/">数据库学习</a>
    </h1>
  

        
        <a href="/blog/2020/04/05/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AD%A6%E4%B9%A0/" class="archive-article-date">
  	<time datetime="2020-04-05T07:16:11.219Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2020-04-05</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>数据库的增删改查已经介绍完毕，今天从表的详细操作开始讲解</p>
<h1 id="表操作"><a href="#表操作" class="headerlink" title="表操作"></a>表操作</h1><h2 id="今日内容"><a href="#今日内容" class="headerlink" title="今日内容"></a>今日内容</h2><h4 id="1-数据类型"><a href="#1-数据类型" class="headerlink" title="1.数据类型"></a>1.数据类型</h4><p>建表的时候，字段都有对应的数据类型</p>
<ul>
<li>整型</li>
<li>浮点型</li>
<li>字符类型(char与varchar)</li>
<li>日期类型</li>
<li>枚举与集合</li>
</ul>
<h4 id="2-约束条件"><a href="#2-约束条件" class="headerlink" title="2.约束条件"></a>2.约束条件</h4><ul>
<li>primary key</li>
<li>unique key</li>
<li>not null</li>
</ul>
<h2 id="详细内容"><a href="#详细内容" class="headerlink" title="详细内容"></a>详细内容</h2><h4 id="创建表的完整语法"><a href="#创建表的完整语法" class="headerlink" title="创建表的完整语法"></a>创建表的完整语法</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#语法：</span></span><br><span class="line">create table 表名(</span><br><span class="line">字段名<span class="number">1</span> 类型[(宽度) 约束条件],</span><br><span class="line">字段名<span class="number">2</span> 类型[(宽度) 约束条件],</span><br><span class="line">字段名<span class="number">3</span> 类型[(宽度) 约束条件]</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">#注意：</span></span><br><span class="line"><span class="number">1.</span> 在同一张表中，字段名不能相同</span><br><span class="line"><span class="number">2.</span> 宽度和约束条件可选，字段名和类型是必须的</span><br><span class="line"><span class="number">3.</span> 最后一个字段后不能加逗号！</span><br><span class="line"></span><br><span class="line"><span class="comment"># 补充：</span></span><br><span class="line"><span class="comment"># 1.宽度指的是对存储数据的限制</span></span><br><span class="line">create table userinfo(name char);</span><br><span class="line">insert into userinfo values(<span class="string">'jason'</span>);</span><br><span class="line"></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">1.没有安全模式的数据库版本，能够存放数据但是只会存进去一个j</span></span><br><span class="line"><span class="string">2.最新数据库版本直接报错提示无法存储:Data too long for column 'name' at row 1</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2.约束条件初识&gt;&gt;&gt; null 与 nut null</span></span><br><span class="line">create table t1(id int,name char <span class="keyword">not</span> null);</span><br><span class="line">insert into t1 values(<span class="number">1</span>,<span class="string">'j'</span>);  <span class="comment"># 正常存储</span></span><br><span class="line">insert into t1 values(<span class="number">2</span>,null);  <span class="comment"># 报错</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 总结 类型与约束条件区别</span></span><br><span class="line"><span class="comment"># 类型：限制字段必须以什么样的数据类型存储</span></span><br><span class="line"><span class="comment"># 约束条件：约束条件是在类型之外添加一种额外的限制</span></span><br></pre></td></tr></table></figure>

<h4 id="基本数据类型"><a href="#基本数据类型" class="headerlink" title="基本数据类型"></a>基本数据类型</h4><h4 id="整型"><a href="#整型" class="headerlink" title="整型"></a>整型</h4><ul>
<li><p>分类：TINYINT SMALLINT MEDIUMINT INT BIGINT</p>
</li>
<li><p>作用：存储年龄，等级，id，各种号码等</p>
</li>
</ul>
<p>类型存储范围：参考图片<a href="http://www.cnblogs.com/linhaifeng/articles/7233411.html" target="_blank" rel="noopener">http://www.cnblogs.com/linhaifeng/articles/7233411.html</a></p>
<p>验证整型字段有无符号及范围</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">create table t1(x tinyint);</span><br><span class="line">insert into t1 values(<span class="number">128</span>),(<span class="number">-129</span>);</span><br><span class="line"></span><br><span class="line">create table t2(x tinyint unsigned);</span><br><span class="line">insert into t2 values(<span class="number">-1</span>),(<span class="number">256</span>);  </span><br><span class="line"></span><br><span class="line">create table t3(x int unsigned);</span><br><span class="line">insert into t3 values(<span class="number">4294967296</span>);</span><br></pre></td></tr></table></figure>

<p><strong>疑问:</strong>类型后面的宽度能否改变字段存储的大小限制</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">create table t4(x int(<span class="number">8</span>));</span><br><span class="line">insert into t4 values(<span class="number">4294967296123</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment"># 显示时，不够8位用0填充，如果超出8位则正常显示</span></span><br><span class="line">create table t5(x int(<span class="number">8</span>) unsigned zerofill);</span><br><span class="line">insert into t5 values(<span class="number">4294967296123</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment"># create table t6(id int(10) unsigned);</span></span><br><span class="line"><span class="comment"># create table t7(id int(11));</span></span><br></pre></td></tr></table></figure>

<p><strong>强调：</strong>对于整型来说，数据类型后的宽度并不是存储限制，而是显示限制，所以在创建表时，如果字段采用的是整型类型，完全无需指定显示宽度， 默认的显示宽度，足够显示完整当初存放的数据</p>
<h3 id="严格模式补充"><a href="#严格模式补充" class="headerlink" title="严格模式补充"></a>严格模式补充</h3><p>我们刚刚在上面设置了char,tinyint,存储数据时超过它们的最大存储长度，发现数据也能正常存储进去，只是mysql帮我们自动截取了最大长度。但在实际情况下，我们应该尽量减少数据库的操作，缓解数据库的压力，让它仅仅只管理数据即可，这样的情况下就需要设置安全模式</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">show variables like <span class="string">"%mode%"</span>;  <span class="comment"># 查看数据库配置中变量名包含mode的配置参数</span></span><br><span class="line"><span class="comment"># 修改安全模式</span></span><br><span class="line">set session <span class="comment"># 只在当前操作界面有效</span></span><br><span class="line">set <span class="keyword">global</span>  <span class="comment"># 全局有效</span></span><br><span class="line"></span><br><span class="line">set <span class="keyword">global</span> sql_mode =<span class="string">'STRICT_TRANS_TABLES'</span></span><br><span class="line"><span class="comment"># 修改完之后退出当前客户端重新登陆即可</span></span><br></pre></td></tr></table></figure>

<h4 id="浮点型"><a href="#浮点型" class="headerlink" title="浮点型"></a>浮点型</h4><ul>
<li>分类:FLOAT DOUBLE decimal</li>
<li>应用场景:身高，体重，薪资</li>
</ul>
<p>字段限制特点(5,3)前一位表示所有的位数，后一位表示小数个数</p>
<p>三者最大整数位和小数位对比:</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 存储限制</span></span><br><span class="line">float(<span class="number">255</span>,<span class="number">30</span>)</span><br><span class="line">double(<span class="number">255</span>,<span class="number">30</span>)</span><br><span class="line">decimal(<span class="number">255</span>,<span class="number">30</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 精确度验证</span></span><br><span class="line">create table t9(x float(<span class="number">255</span>,<span class="number">30</span>));</span><br><span class="line">create table t10(x double(<span class="number">255</span>,<span class="number">30</span>));</span><br><span class="line">create table t11(x decimal(<span class="number">65</span>,<span class="number">30</span>));</span><br><span class="line"></span><br><span class="line">insert into t9 values(<span class="number">1.111111111111111111111111111111</span>);</span><br><span class="line">insert into t10 values(<span class="number">1.111111111111111111111111111111</span>);</span><br><span class="line">insert into t11 values(<span class="number">1.111111111111111111111111111111</span>);</span><br></pre></td></tr></table></figure>

<h4 id="字符类型"><a href="#字符类型" class="headerlink" title="字符类型"></a>字符类型</h4><ul>
<li>分类<ul>
<li>char(定长)</li>
<li>varchar(变长)</li>
</ul>
</li>
<li>作用:姓名，地址，描述类信息</li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">create table t10(name char(<span class="number">4</span>))  <span class="comment"># 超出四个字符报错，不够四个字符空格补全</span></span><br><span class="line">create table t11(name varchar(<span class="number">4</span>))  <span class="comment"># 超出四个字符报错，不够四个有几个就存几个</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证存储限制</span></span><br><span class="line">insert into t12 values(<span class="string">'hello'</span>);</span><br><span class="line">insert into t13 values(<span class="string">'hello'</span>);</span><br><span class="line"><span class="comment"># 验证存储长度</span></span><br><span class="line">insert into t12 values(<span class="string">'a'</span>); <span class="comment">#'a    '</span></span><br><span class="line">insert into t13 values(<span class="string">'a'</span>); <span class="comment">#'a'</span></span><br><span class="line">select * <span class="keyword">from</span> t12</span><br><span class="line">select * <span class="keyword">from</span> t13  <span class="comment"># 无法查看真正的结果</span></span><br><span class="line"></span><br><span class="line">select char_length(name) <span class="keyword">from</span> t12</span><br><span class="line">select char_length(name) <span class="keyword">from</span> t13  <span class="comment"># 仍然无法查看到真正的结果</span></span><br><span class="line"></span><br><span class="line"><span class="string">"""首先应该肯定的是在硬盘上存的绝对是真正的数据，但显示的时候mysql会自动将末尾的空格取掉"""</span></span><br><span class="line"><span class="comment"># 如果不想让mysql帮你做自动去除末尾空格的操作，需要再添加一个模式</span></span><br><span class="line">set <span class="keyword">global</span> sql_mode=<span class="string">"strict_trans_tables,PAD_CHAR_TO_FULL_LENGTH"</span>;</span><br><span class="line"><span class="comment"># 退出客户端重新登陆</span></span><br><span class="line">select char_length(x) <span class="keyword">from</span> t12; <span class="comment">#4</span></span><br><span class="line">select char_length(y) <span class="keyword">from</span> t13; <span class="comment">#1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 针对char类型，mysql在存储时会将数据用空格补全存放到硬盘中。但是会在读出结果的时候自动取掉末尾的空格</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">char与varchar的使用区别</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line">name char(<span class="number">5</span>)</span><br><span class="line"><span class="comment"># 缺点：浪费空间</span></span><br><span class="line"><span class="comment"># 优点：存取速度都快</span></span><br><span class="line">egon alex lxx  jxx  txx  </span><br><span class="line"></span><br><span class="line">name varchar(<span class="number">5</span>)</span><br><span class="line"><span class="comment"># 缺点：存取速度慢</span></span><br><span class="line"><span class="comment"># 优点：节省空间</span></span><br><span class="line"><span class="number">1</span>bytes+egon <span class="number">1</span>bytes+alex <span class="number">1</span>bytes+lxx  <span class="number">1</span>bytes+jxx  <span class="number">1</span>bytes+txx</span><br></pre></td></tr></table></figure>

<h4 id="时间类型"><a href="#时间类型" class="headerlink" title="时间类型"></a>时间类型</h4><ul>
<li><p>分类</p>
<ul>
<li>date：2019-05-01</li>
<li>time：11:11:11</li>
<li>Datetime: 2019-01-02 11:11:11</li>
<li>Year:2019</li>
</ul>
</li>
<li><p>测试</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">create table student(</span><br><span class="line">	id int,</span><br><span class="line">  name char(16),</span><br><span class="line">  born_year year,</span><br><span class="line">  birth date,</span><br><span class="line">  study_time time,</span><br><span class="line">  reg_time datetime</span><br><span class="line">);</span><br><span class="line">insert into student values(1,&#39;egon&#39;,&#39;2019&#39;,&#39;2019-05-09&#39;,&#39;11:11:00&#39;,&#39;2019-11-11 11:11:11&#39;);</span><br></pre></td></tr></table></figure>

</li>
</ul>
<h4 id="枚举与集合类型"><a href="#枚举与集合类型" class="headerlink" title="枚举与集合类型"></a>枚举与集合类型</h4><ul>
<li><p>分类</p>
<ul>
<li>枚举enum 多选一</li>
<li>集合set 多选多</li>
</ul>
</li>
<li><p>测试</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">create table user(</span><br><span class="line">	id int,</span><br><span class="line">  name char(16),</span><br><span class="line">  gender enum(&#39;male&#39;,&#39;female&#39;,&#39;others&#39;)</span><br><span class="line">);</span><br><span class="line">insert into user values(1,&#39;jason&#39;,&#39;xxx&#39;)  # 报错</span><br><span class="line">insert into user values(2,&#39;egon&#39;,&#39;female&#39;)  # 正确！</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">create table teacher(</span><br><span class="line">	id int,</span><br><span class="line">  name char(16),</span><br><span class="line">  gender enum(&#39;male&#39;,&#39;female&#39;,&#39;others&#39;),</span><br><span class="line">  hobby set(&#39;read&#39;,&#39;sleep&#39;,&#39;sanna&#39;,&#39;dbj&#39;)</span><br><span class="line">);</span><br><span class="line">insert into teacher values(1,&#39;egon&#39;,&#39;male&#39;,&#39;read,sleep,dbj&#39;)  # 集合也可以只存一个</span><br></pre></td></tr></table></figure>



</li>
</ul>
<h2 id="约束条件"><a href="#约束条件" class="headerlink" title="约束条件"></a>约束条件</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">PRIMARY KEY (PK)    标识该字段为该表的主键，可以唯一的标识记录</span></span><br><span class="line"><span class="string">FOREIGN KEY (FK)    标识该字段为该表的外键</span></span><br><span class="line"><span class="string">NOT NULL    标识该字段不能为空</span></span><br><span class="line"><span class="string">UNIQUE KEY (UK)    标识该字段的值是唯一的</span></span><br><span class="line"><span class="string">AUTO_INCREMENT    标识该字段的值自动增长（整数类型，而且为主键）</span></span><br><span class="line"><span class="string">DEFAULT    为该字段设置默认值</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">UNSIGNED 无符号</span></span><br><span class="line"><span class="string">ZEROFILL 使用0填充</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></table></figure>

<h4 id="not-null-default"><a href="#not-null-default" class="headerlink" title="not null+default"></a>not null+default</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">create table user(</span><br><span class="line">	id int,</span><br><span class="line">  name char(16)</span><br><span class="line">);</span><br><span class="line">insert into user values(1,null)  # 可以修改</span><br><span class="line"></span><br><span class="line">alter table user modify name char(16) not null;</span><br><span class="line">insert into user(name,id) values(null,2);  # 报错 插入数据可以在表名后面指定插入数据对应的字段</span><br><span class="line"></span><br><span class="line">create table student(</span><br><span class="line">	id int,</span><br><span class="line">  name char(16) not null,</span><br><span class="line">  gender enum(&#39;male&#39;,&#39;female&#39;,&#39;others&#39;) default &#39;male&#39;</span><br><span class="line">)</span><br><span class="line">insert into student(id,name) values(1,&#39;jason&#39;)  # 成功</span><br></pre></td></tr></table></figure>

<h4 id="unique"><a href="#unique" class="headerlink" title="unique"></a>unique</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"># 单列唯一</span><br><span class="line">create table user1(</span><br><span class="line">	id int unique, </span><br><span class="line">  name char(16)</span><br><span class="line">);</span><br><span class="line">insert into user1 values(1,&#39;jason&#39;),(1,&#39;egon&#39;)  # 报错</span><br><span class="line">insert into user1 values(1,&#39;jason&#39;),(2,&#39;egon&#39;)  # 成功</span><br><span class="line"></span><br><span class="line"># 联合唯一</span><br><span class="line">create table server(</span><br><span class="line">	id int,</span><br><span class="line">  ip char(16),</span><br><span class="line">  port int,</span><br><span class="line">  unique(ip,port)</span><br><span class="line">)</span><br><span class="line">insert into server values(1,&#39;127.0.0.1&#39;,8080);</span><br><span class="line">insert into server values(2,&#39;127.0.0.1&#39;,8080);  # 报错</span><br><span class="line">insert into server values(1,&#39;127.0.0.1&#39;,8081);</span><br></pre></td></tr></table></figure>

<h4 id="primary-key-auto-increment"><a href="#primary-key-auto-increment" class="headerlink" title="primary key+auto_increment"></a>primary key+auto_increment</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"># 单从约束角度来说primary key就等价于not null unique</span><br><span class="line">create table t11(id int primary key);</span><br><span class="line">desc t11;</span><br><span class="line">insert into t11 values(1),(1);  # 报错</span><br><span class="line">insert into t11 values(1),(2);</span><br><span class="line"></span><br><span class="line"># 除了约束之外，它还是innodb引擎组织数据的依据，提升查询效率</span><br><span class="line">&quot;&quot;&quot;</span><br><span class="line">强调:</span><br><span class="line">1.一张表中必须有且只有一个主键，如果你没有设置主键，那么会从上到下搜索直到遇到一个非空且唯一的字段自动将其设置为主键</span><br><span class="line">&quot;&quot;&quot;</span><br><span class="line">create table t12(</span><br><span class="line">	id int,</span><br><span class="line">  name char(16),</span><br><span class="line">  age int not null unique,</span><br><span class="line">  addr char(16) not null unique</span><br><span class="line">)engine&#x3D;innodb;</span><br><span class="line">desc t12;</span><br><span class="line">&quot;&quot;&quot;</span><br><span class="line">2.如果表里面没有指定任何的可以设置为主键的字段，那么innodb会采用自己默认的一个隐藏字段作为主键，隐藏意味着你在查询的时候无法根据这个主键字段加速查询了</span><br><span class="line">索引：类似于书的目录，没有主键就相当于一页一页翻着查</span><br><span class="line">3.一张表中通常都应该有一个id字段，并且通常将改id字段作成主键</span><br><span class="line">&quot;&quot;&quot;</span><br><span class="line"># 联合主键：多个字段联合起来作为表的一个主键，本质还是一个主键</span><br><span class="line">create table t18(</span><br><span class="line">	ip char(16),</span><br><span class="line">  port int,</span><br><span class="line">  primary key(ip,port)</span><br><span class="line">);</span><br><span class="line">desc t18;</span><br><span class="line"></span><br><span class="line"># 主键id作为数据的编号，每次最好能自动递增</span><br><span class="line">create table t13(</span><br><span class="line">	id int primary key auto_increment,</span><br><span class="line">  name char(16)</span><br><span class="line">);</span><br><span class="line">insert into t13(&#39;jason&#39;),(&#39;jason&#39;),(&#39;jason&#39;);  # id字段自动从1开始递增</span><br><span class="line"># 注意：auto_increment通常都是加在主键上，并且只能给设置为key的字段加</span><br></pre></td></tr></table></figure>

<h4 id="补充："><a href="#补充：" class="headerlink" title="补充："></a>补充：</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">delete from tb1;</span><br><span class="line">强调：上面的这条命令确实可以将表里的所有记录都删掉，但不会将id重置为0，</span><br><span class="line">所以收该条命令根本不是用来清空表的，delete是用来删除表中某一些符合条件的记录</span><br><span class="line">delete from tb1 where id &gt; 10;</span><br><span class="line"></span><br><span class="line">如果要清空表，使用truncate tb1；</span><br><span class="line">作用：将整张表重置,id重新从0开始记录</span><br></pre></td></tr></table></figure>


      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/blog/2020/04/05/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AD%A6%E4%B9%A0/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-爬虫相关" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/02/28/%E7%88%AC%E8%99%AB%E7%9B%B8%E5%85%B3/">爬虫相关</a>
    </h1>
  

        
        <a href="/blog/2020/02/28/%E7%88%AC%E8%99%AB%E7%9B%B8%E5%85%B3/" class="archive-article-date">
  	<time datetime="2020-02-28T04:26:51.168Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2020-02-28</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h1 id="1、爬虫是啥？"><a href="#1、爬虫是啥？" class="headerlink" title="1、爬虫是啥？"></a>1、爬虫是啥？</h1><h1 id="2、http协议里需要关注的"><a href="#2、http协议里需要关注的" class="headerlink" title="2、http协议里需要关注的"></a>2、http协议里需要关注的</h1><h1 id="3、-常用请求库、解析库、数据库的用法"><a href="#3、-常用请求库、解析库、数据库的用法" class="headerlink" title="3、 常用请求库、解析库、数据库的用法"></a>3、 常用请求库、解析库、数据库的用法</h1><h2 id="3-1-常用请求库-测试网站：http-httpbin-org-get"><a href="#3-1-常用请求库-测试网站：http-httpbin-org-get" class="headerlink" title="3.1 常用请求库    测试网站：http://httpbin.org/get"></a>3.1 常用请求库    测试网站：<a href="http://httpbin.org/get" target="_blank" rel="noopener">http://httpbin.org/get</a></h2><h3 id="request库"><a href="#request库" class="headerlink" title="request库"></a>request库</h3><p>​    <strong>安装</strong>：pip install requests</p>
<p>​    <strong>使用</strong>：</p>
<p>​        <strong>请求</strong>：</p>
<p>​            <strong>①get请求：</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">				响应对象 &#x3D; requests.get(......)</span><br><span class="line"></span><br><span class="line">​				**参数：**</span><br><span class="line"></span><br><span class="line">​					url：</span><br><span class="line"></span><br><span class="line">​					headers &#x3D; &#123;&#125;</span><br><span class="line"></span><br><span class="line">​					cookies &#x3D; &#123;&#125;</span><br><span class="line"></span><br><span class="line">​					params &#x3D; &#123;&#125;	</span><br><span class="line"></span><br><span class="line">​					proxies &#x3D; &#123;&#39;http&#39;：‘http:&#x2F;&#x2F;端口：ip’&#125;</span><br><span class="line"></span><br><span class="line">​					timeout &#x3D; 0.5</span><br><span class="line"></span><br><span class="line">​					allow_redirects &#x3D; False</span><br></pre></td></tr></table></figure>



<p>​            <strong>②post请求：</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">				响应对象 &#x3D; requests.post(......)</span><br><span class="line"></span><br><span class="line">​				**参数：**</span><br><span class="line"></span><br><span class="line">​					url：</span><br><span class="line"></span><br><span class="line">​					headers &#x3D; &#123;&#125;</span><br><span class="line"></span><br><span class="line">​					cookies &#x3D; &#123;&#125;</span><br><span class="line"></span><br><span class="line">​					data &#x3D; &#123;&#125;</span><br><span class="line"></span><br><span class="line">​					json &#x3D; &#123;&#125;</span><br><span class="line"></span><br><span class="line">​					files &#x3D; &#123;‘file’：open（...，‘rb’）&#125;</span><br><span class="line"></span><br><span class="line">​					timeout &#x3D; 0.5</span><br><span class="line"></span><br><span class="line">​					allow_redirects &#x3D; False</span><br></pre></td></tr></table></figure>

<p>​        <strong>自动保存cookie的请求：</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">			session &#x3D; requests.session（）</span><br><span class="line"></span><br><span class="line">​			r &#x3D; session.get(......)</span><br><span class="line"></span><br><span class="line">​			r &#x3D; session.post(......)</span><br><span class="line">	  补充:(保存cookie到本地)</span><br><span class="line">	  	import http.cookiejar as cookielib</span><br><span class="line">	  	session.cookie &#x3D; cookielib.LWPCookieJar()</span><br><span class="line">	  	session.cookie.save(filename&#x3D;&#39;1.txt&#39;)</span><br><span class="line">	  	</span><br><span class="line">	  	session.cookies.load(filename&#x3D;&#39;1.txt&#39;)</span><br></pre></td></tr></table></figure>

<p>​        <strong>响应：</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">			r.url    获取请求的url</span><br><span class="line"></span><br><span class="line">​			r.text		获取相应文本信息</span><br><span class="line"></span><br><span class="line">​			r.encoding &#x3D; &#39;gbk&#39;   </span><br><span class="line"></span><br><span class="line">​			r.content   二进制</span><br><span class="line"></span><br><span class="line">​			r.json()    json.loads(r.text)</span><br><span class="line"></span><br><span class="line">​			r.status_code   响应状态码</span><br><span class="line"></span><br><span class="line">​			r.headers  	相应头</span><br><span class="line"></span><br><span class="line">​			r.cookies	相应cookie（set——cookie）</span><br><span class="line"></span><br><span class="line">​			r.history    【相应对象，响应对象。。。】</span><br></pre></td></tr></table></figure>



<h2 id="3-2-常用解析语法"><a href="#3-2-常用解析语法" class="headerlink" title="3.2 常用解析语法"></a>3.2 常用解析语法</h2><h3 id="css选择器"><a href="#css选择器" class="headerlink" title="css选择器"></a>css选择器</h3><p>​    1、类选择器</p>
<p>​        .类名</p>
<p>​    2、id选择器</p>
<p>​        #id值</p>
<p>​    3、标签选择器</p>
<p>​        标签名</p>
<p>​    4、后代选择器</p>
<p>​        选择器1  选择器2</p>
<p>​    5、子选择器</p>
<p>​        选择器1&gt;选择器2</p>
<p>​    6、属性选择器</p>
<p>​        【属性名】  【name】</p>
<p>​        【属性名=值】  【name=‘title’】</p>
<p>​        【属性名^=值】   属性以。。开头</p>
<p>​        【属性名$=值】   结尾</p>
<p>​        【属性名*=值】   包含</p>
<p>​    7、群组选择器</p>
<p>​        选择器1，选择器2          or   </p>
<p>​    8、多条件选择器</p>
<p>​        选择器1选择器2           and</p>
<p>​        p【属性=值】</p>
<h3 id="xpath选择器"><a href="#xpath选择器" class="headerlink" title="xpath选择器"></a>xpath选择器</h3><p>​    略</p>
<h2 id="3-3-牛逼的requests-html"><a href="#3-3-牛逼的requests-html" class="headerlink" title="3.3 牛逼的requests-html"></a>3.3 牛逼的requests-html</h2><p>​    <strong>安装：</strong> pip install requests-html</p>
<p>​    <strong>使用：</strong></p>
<p>​        <strong>请求：</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">			from requests_html import HTMLSession</span><br><span class="line"></span><br><span class="line">​			session &#x3D; HTMLSession()</span><br><span class="line"></span><br><span class="line">​			**参数：**</span><br><span class="line"></span><br><span class="line">​				browser.args &#x3D; [</span><br><span class="line"></span><br><span class="line">​					&#39;--no-sand&#39;,</span><br><span class="line"></span><br><span class="line">​					&#39;--user-agent&#x3D;XXXXX&#39;</span><br><span class="line"></span><br><span class="line">​				]</span><br><span class="line"></span><br><span class="line">​			响应对象 &#x3D; session.request（......）</span><br><span class="line"></span><br><span class="line">​			响应对象 &#x3D; session.get（......）</span><br><span class="line"></span><br><span class="line">​			响应对象 &#x3D; session.post（......）</span><br></pre></td></tr></table></figure>

<p>​            <strong>参数和requests模块一毛一样</strong></p>
<p>​        <strong>响应：</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">			r.url</span><br><span class="line"></span><br><span class="line">​			**属性和requests模块一毛一样</span><br></pre></td></tr></table></figure>

<p>**</p>
<p>​        <strong>解析：</strong></p>
<p>​        <strong>html对象属性：</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">			r.html.absolute_links      绝对路径    基础路径 + &#x2F;d&#x2F;ffdsadfsadas.jpg</span><br><span class="line"></span><br><span class="line">​				   .links				相对路径</span><br><span class="line"></span><br><span class="line">​			           .base_url       基础路径</span><br><span class="line"></span><br><span class="line">​			           .html          拿到页面内容  （相当于r.text）</span><br><span class="line"></span><br><span class="line">​			           .text          拿到页面上纯文本</span><br><span class="line"></span><br><span class="line">​			           .encoding &#x3D; &#39;gbk&#39;  </span><br><span class="line"></span><br><span class="line">​			           .raw_html      相当于r.context</span><br><span class="line"></span><br><span class="line">​			           .qp</span><br></pre></td></tr></table></figure>

<p>​        <strong>html对象方法：</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">			r.html.find(&#39;css选择器&#39;)                   【element对象，element对象，】</span><br><span class="line"></span><br><span class="line">​				   .find(&#39;css选择器&#39;，first &#x3D; True)     element对象</span><br><span class="line"></span><br><span class="line">​				   .xpath(‘xpath选择器’)</span><br><span class="line"></span><br><span class="line">​				   .xpath(&#39;‘xpath选择器&#39;，first &#x3D; True)</span><br><span class="line"></span><br><span class="line">​				   .search(‘模板’)                     search对象</span><br><span class="line"></span><br><span class="line">​			           	（‘xxx&#123;&#125;yyy&#123;&#125;’）[0]</span><br><span class="line"></span><br><span class="line">​					   （‘xxx&#123;name&#125;yyy&#123;pwd&#125;’）[‘name’]</span><br><span class="line"></span><br><span class="line">​				   .search_all(&#39;模板&#39;)                【search对象。search对象】</span><br><span class="line"></span><br><span class="line">​				   .render(.....)</span><br><span class="line"></span><br><span class="line">​				   	**参数：**</span><br><span class="line"></span><br><span class="line">​					    	scripy：“”“ ( ) &#x3D;&gt; &#123;</span><br><span class="line"></span><br><span class="line">​										js代码</span><br><span class="line"></span><br><span class="line">​										js代码</span><br><span class="line"></span><br><span class="line">​									&#125;</span><br><span class="line"></span><br><span class="line">​								  ”“”</span><br><span class="line"></span><br><span class="line">​						    scrolldow：n</span><br><span class="line"></span><br><span class="line">​						    sleep:n</span><br><span class="line"></span><br><span class="line">​						    keep_page:True&#x2F;False</span><br></pre></td></tr></table></figure>



<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">()&#x3D;&gt;&#123;</span><br><span class="line">Object.defineProperties(navigator,&#123;</span><br><span class="line">        webdriver:&#123;</span><br><span class="line">        get: () &#x3D;&gt; undefined</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br></pre></td></tr></table></figure>

<p>​        <strong>与浏览器交互    r.html.page.XXX</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">				asynic def xxx():</span><br><span class="line"></span><br><span class="line">​					await r.html.page.XXX</span><br><span class="line"></span><br><span class="line">​				session.loop.run....(xxx())</span><br><span class="line"></span><br><span class="line">​			.screenshot(&#123;&#39;path&#39;:路径&#125;)</span><br><span class="line"></span><br><span class="line">​			.evaluate(&#39;&#39;&#39;() &#x3D;&gt;&#123;js代码&#125;’‘’&#125;)</span><br><span class="line"></span><br><span class="line">​			.cookies()</span><br><span class="line"></span><br><span class="line">​			.type(&#39;css选择器&#39;，’内容‘，&#123;’delay‘：100&#125;)</span><br><span class="line"></span><br><span class="line">​			.click(&#39;css选择器&#39;)</span><br><span class="line"></span><br><span class="line">​			.focus(&#39;css选择器&#39;)</span><br><span class="line"></span><br><span class="line">​			.hover(&#39;css选择器&#39;)</span><br><span class="line"></span><br><span class="line">​			.waitForSelector(&#39;css选择器&#39;)</span><br><span class="line"></span><br><span class="line">​			.waitFor(1000)</span><br></pre></td></tr></table></figure>

<p>​        <strong>键盘事件    r.html.page.keyboard.XXX</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">			.down(&#39;Shift&#39;)</span><br><span class="line"></span><br><span class="line">​			.up(&#39;Shift&#39;)</span><br><span class="line"></span><br><span class="line">​			.press(&#39;ArrowLeft&#39;)</span><br><span class="line"></span><br><span class="line">​			.type(&#39;喜欢你啊&#39;，&#123;‘delay’:100&#125;)</span><br></pre></td></tr></table></figure>

<p>​        <strong>鼠标事件    r.html.page.mouse.XXX</strong></p>
<p>​            </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">.click(x,y,&#123;</span><br><span class="line">             &#39;button&#39;：&#39;left&#39;,</span><br><span class="line">             &#39;click&#39;:1</span><br><span class="line">             &#39;delay&#39;:0</span><br><span class="line">&#125;)</span><br><span class="line">.down(&#123;&#39;button&#39;：&#39;left&#39;&#125;)</span><br><span class="line">.up(&#123;&#39;button&#39;：&#39;left&#39;&#125;)</span><br><span class="line">.move(x,y,&#123;&#39;steps&#39;：1&#125;)</span><br></pre></td></tr></table></figure>

<p>​            .</p>
<h2 id="常用数据库"><a href="#常用数据库" class="headerlink" title="常用数据库"></a>常用数据库</h2><p>###mongoDB4.0:</p>
<p>下载:<a href="https://www.mongodb.com/" target="_blank" rel="noopener">https://www.mongodb.com/</a></p>
<p>安装:略</p>
<p><strong>注意:</strong>使用前修改bin目录下配置文件mongodb.cfg,删除最后一行的’mp’字段</p>
<p>####1. 启动服务与终止服务</p>
<p>net start mongodb</p>
<p>net stop mongodb</p>
<h4 id="2-创建管理员用户"><a href="#2-创建管理员用户" class="headerlink" title="2.创建管理员用户"></a>2.创建管理员用户</h4><p>mongo</p>
<p>use admin</p>
<p>db.createUser({user:”yxp”,pwd:”997997”,roles:[“root”]})</p>
<h4 id="3-使用账户密码连接mongodb"><a href="#3-使用账户密码连接mongodb" class="headerlink" title="3.使用账户密码连接mongodb"></a>3.使用账户密码连接mongodb</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mongo -u adminUserName -p userPassword --authenticationDatabase admin</span><br></pre></td></tr></table></figure>

<h4 id="4-数据库"><a href="#4-数据库" class="headerlink" title="4.数据库"></a>4.数据库</h4><h5 id="查看数据库"><a href="#查看数据库" class="headerlink" title="查看数据库"></a>查看数据库</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">show dbs 查看数据库</span><br></pre></td></tr></table></figure>

<h5 id="切换数据库"><a href="#切换数据库" class="headerlink" title="切换数据库"></a>切换数据库</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">use db_name 切换数据库</span><br></pre></td></tr></table></figure>

<h5 id="增加数据库"><a href="#增加数据库" class="headerlink" title="增加数据库"></a>增加数据库</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">db.table1.insert(&#123;&#39;a&#39;:1&#125;)  创建数据库(切换到数据库插入表及数据)</span><br></pre></td></tr></table></figure>

<h5 id="删除数据库"><a href="#删除数据库" class="headerlink" title="删除数据库"></a>删除数据库</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">db.dropDatabase()  删数据库(删前要切换)</span><br></pre></td></tr></table></figure>

<h4 id="5-表"><a href="#5-表" class="headerlink" title="5.表"></a>5.表</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">使用前先切换数据库</span><br></pre></td></tr></table></figure>

<h5 id="查看表"><a href="#查看表" class="headerlink" title="查看表"></a>查看表</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">show tables 查所有的表</span><br></pre></td></tr></table></figure>

<h5 id="增加表"><a href="#增加表" class="headerlink" title="增加表"></a>增加表</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">db.table1.insert(&#123;&#39;b&#39;:2&#125;)  增加表(表不存在就创建)</span><br></pre></td></tr></table></figure>

<h5 id="删除表"><a href="#删除表" class="headerlink" title="删除表"></a>删除表</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">db.table1.drop()    删表</span><br></pre></td></tr></table></figure>

<h4 id="数据"><a href="#数据" class="headerlink" title="数据"></a>数据</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">db.test.insert(user0)    插入一条</span><br><span class="line">db.user.insertMany([user1,user2,user3,user4,user5])   插入多条</span><br><span class="line">db.user.find(&#123;&#39;name&#39;:&#39;alex&#39;&#125;)   查xx&#x3D;&#x3D;xx</span><br><span class="line">db.user.find(&#123;&#39;name&#39;:&#123;&quot;$ne&quot;:&#39;alex&#39;&#125;&#125;)   查xx!&#x3D;xx</span><br><span class="line">db.user.find(&#123;&#39;_id&#39;:&#123;&#39;$gt&#39;:2&#125;&#125;)    查xx&gt;xx</span><br><span class="line">db.user.find(&#123;&quot;_id&quot;:&#123;&quot;$gte&quot;:2,&#125;&#125;)  查xx&gt;&#x3D;xx</span><br><span class="line">db.user.find(&#123;&#39;_id&#39;:&#123;&#39;$lt&#39;:3&#125;&#125;)  查xx&lt;xx</span><br><span class="line">db.user.find(&#123;&quot;_id&quot;:&#123;&quot;$lte&quot;:2&#125;&#125;)  查xx&lt;&#x3D;xx</span><br><span class="line">db.user.update(&#123;&#39;_id&#39;:2&#125;,&#123;&quot;$set&quot;:&#123;&quot;name&quot;:&quot;WXX&quot;,&#125;&#125;)   改数据</span><br><span class="line">db.user.deleteOne(&#123; &#39;age&#39;: 8 &#125;)   删第一个匹配</span><br><span class="line">db.user.deleteMany( &#123;&#39;addr.country&#39;: &#39;China&#39;&#125; )  删全部匹配</span><br><span class="line">db.user.deleteMany(&#123;&#125;)  删所有</span><br></pre></td></tr></table></figure>

<h4 id="pymongo"><a href="#pymongo" class="headerlink" title="pymongo"></a>pymongo</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">conn &#x3D; pymongo.MongoClient(host&#x3D;host,port&#x3D;port, username&#x3D;username, password&#x3D;password)</span><br><span class="line">db &#x3D; client[&quot;db_name&quot;] 切换数据库</span><br><span class="line">table &#x3D; db[&#39;表名&#39;]</span><br><span class="line">table.insert(&#123;&#125;)  插入数据</span><br><span class="line">table.remove(&#123;&#125;)   删除数据</span><br><span class="line">table.update(&#123;&#39;_id&#39;:2&#125;,&#123;&quot;$set&quot;:&#123;&quot;name&quot;:&quot;WXX&quot;,&#125;&#125;)   改数据</span><br><span class="line">table.find(&#123;&#125;)  查数据</span><br></pre></td></tr></table></figure>



<h1 id="爬虫与反爬虫的对抗历史"><a href="#爬虫与反爬虫的对抗历史" class="headerlink" title="爬虫与反爬虫的对抗历史"></a>爬虫与反爬虫的对抗历史</h1><p><img src="%E9%85%8D%E5%9B%BE/20180422104137679.png" alt="1565136366701"></p>
<h1 id="常见反扒手段"><a href="#常见反扒手段" class="headerlink" title="常见反扒手段"></a>常见反扒手段</h1><p>1.检测浏览器headers</p>
<p>2.ip封禁</p>
<p>3.图片验证码</p>
<p>4.滑动模块</p>
<p>5.js轨迹</p>
<p>6.前端反调试</p>
<h1 id="小爬爬"><a href="#小爬爬" class="headerlink" title="小爬爬"></a>小爬爬</h1><p>1.爬校花图片</p>
<p>2.爬豆瓣电影</p>
<p>3.校花电影m3u8</p>
<p>4.爬取天猫</p>
<p>​    反爬虫:使用技术手段防止爬虫程序的方法</p>
<p>​    误伤:反扒技术将普通用户识别为爬虫,如果误伤过高,效果再好也不能用</p>
<p>​    成本:反爬虫需要的人力和机器成本</p>
<p>​    拦截:成功拦截爬虫,一般情况下,拦截率越高,误伤率越高</p>
<p>5.分析腾讯视频url</p>
<p>​    接口:<a href="https://p2p.1616jx.com/api/api.php?url=vip视频地址" target="_blank" rel="noopener">https://p2p.1616jx.com/api/api.php?url=vip视频地址</a></p>
<p>6.登录知乎</p>
<p>​    保存cookie到本地</p>
<p>7.红薯小说(js注入)</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">script&#x3D;&#39;&#39;&#39;</span><br><span class="line">var span_list &#x3D; document.getElementsByTagName(&quot;span&quot;)</span><br><span class="line">for (var i&#x3D;0;i&lt;span_list.length;i++)&#123;</span><br><span class="line">    var content &#x3D; window.getComputedStyle(</span><br><span class="line">        span_list[i], &#39;:before&#39;</span><br><span class="line">    ).getPropertyValue(&#39;content&#39;);</span><br><span class="line">    span_list[i].innerText &#x3D; content.replace(&#39;&quot;&#39;,&quot;&quot;).replace(&#39;&quot;&#39;,&quot;&quot;);</span><br><span class="line">&#125;</span><br><span class="line">&#39;&#39;&#39;</span><br></pre></td></tr></table></figure>


      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/blog/2020/02/28/%E7%88%AC%E8%99%AB%E7%9B%B8%E5%85%B3/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-Vue" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/02/28/Vue/">Vue</a>
    </h1>
  

        
        <a href="/blog/2020/02/28/Vue/" class="archive-article-date">
  	<time datetime="2020-02-28T04:26:42.888Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2020-02-28</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h1 id="Vue"><a href="#Vue" class="headerlink" title="Vue"></a><a href="https://cn.vuejs.org/" target="_blank" rel="noopener">Vue</a></h1><h3 id="渐进式-JavaScript-框架"><a href="#渐进式-JavaScript-框架" class="headerlink" title="渐进式 JavaScript 框架"></a><em>渐进式 JavaScript 框架</em></h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">通过对框架的了解与运用程度，来决定其在整个项目中的应用范围，最终可以独立以框架方式完成整个web前端项目</span><br></pre></td></tr></table></figure>



<h2 id="一、走进Vue"><a href="#一、走进Vue" class="headerlink" title="一、走进Vue"></a>一、走进Vue</h2><h4 id="1、what-–-什么是Vue"><a href="#1、what-–-什么是Vue" class="headerlink" title="1、what – 什么是Vue"></a>1、what – 什么是Vue</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">可以独立完成前后端分离式web项目的JavaScript框架</span><br></pre></td></tr></table></figure>

<h4 id="2、why-–-为什么要学习Vue"><a href="#2、why-–-为什么要学习Vue" class="headerlink" title="2、why – 为什么要学习Vue"></a>2、why – 为什么要学习Vue</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">三大主流框架之一：Angular React Vue</span><br><span class="line">先进的前端设计模式：MVVM</span><br><span class="line">可以完全脱离服务器端，以前端代码复用的方式渲染整个页面：组件化开发</span><br></pre></td></tr></table></figure>

<h4 id="3、special-–-特点"><a href="#3、special-–-特点" class="headerlink" title="3、special – 特点"></a>3、special – 特点</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">单页面web应用</span><br><span class="line">数据驱动</span><br><span class="line">数据的双向绑定</span><br><span class="line">虚拟DOM</span><br></pre></td></tr></table></figure>

<h4 id="4、how-–-如何使用Vue"><a href="#4、how-–-如何使用Vue" class="headerlink" title="4、how – 如何使用Vue"></a>4、how – 如何使用Vue</h4><ul>
<li>开发版本：<a href="https://vuejs.org/js/vue.js" target="_blank" rel="noopener">vue.js</a></li>
<li>生产版本：<a href="https://vuejs.org/js/vue.min.js" target="_blank" rel="noopener">vue.min.js</a></li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line">	&#123;&#123; &#125;&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"js/vue.min.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="actionscript">	<span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">		el: <span class="string">'#app'</span></span></span><br><span class="line">	&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>



<h2 id="二、Vue实例"><a href="#二、Vue实例" class="headerlink" title="二、Vue实例"></a>二、Vue实例</h2><h4 id="1、el：实例"><a href="#1、el：实例" class="headerlink" title="1、el：实例"></a>1、el：实例</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> Vue(&#123;</span><br><span class="line">    el: <span class="string">'#app'</span></span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 实例与页面挂载点一一对应</span></span><br><span class="line"><span class="comment">// 一个页面中可以出现多个实例对应多个挂载点</span></span><br><span class="line"><span class="comment">// 实例只操作挂载点内部内容</span></span><br></pre></td></tr></table></figure>

<h4 id="2、data：数据"><a href="#2、data：数据" class="headerlink" title="2、data：数据"></a>2、data：数据</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">'app'</span>&gt;</span></span><br><span class="line">    &#123;&#123; msg &#125;&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="actionscript">    <span class="keyword">var</span> app = <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">    	el: <span class="string">'#app'</span>,</span></span><br><span class="line">    	data: &#123;</span><br><span class="line"><span class="actionscript">    		msg: <span class="string">'数据'</span>,</span></span><br><span class="line">    	&#125;</span><br><span class="line">    &#125;)</span><br><span class="line"><span class="javascript">    <span class="built_in">console</span>.log(app.$data.msg);</span></span><br><span class="line"><span class="javascript">    <span class="built_in">console</span>.log(app.msg);</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- data为插件表达式中的变量提供数据 --&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- data中的数据可以通过Vue实例直接或间接访问--&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="3、methods：方法"><a href="#3、methods：方法" class="headerlink" title="3、methods：方法"></a>3、methods：方法</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css">    <span class="selector-class">.box</span> &#123; <span class="attribute">background-color</span>: orange &#125;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">'app'</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">"box"</span> <span class="attr">v-on:click</span>=<span class="string">"pClick"</span>&gt;</span>测试<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">"box"</span> <span class="attr">v-on:mouseover</span>=<span class="string">"pOver"</span>&gt;</span>测试<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="actionscript">    <span class="keyword">var</span> app = <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">    	el: <span class="string">'#app'</span>,</span></span><br><span class="line">    	methods: &#123;</span><br><span class="line">            pClick () &#123;</span><br><span class="line"><span class="actionscript">                <span class="comment">// 点击测试</span></span></span><br><span class="line">            &#125;,</span><br><span class="line">            pOver () &#123;</span><br><span class="line"><span class="actionscript">                <span class="comment">// 悬浮测试</span></span></span><br><span class="line">            &#125;</span><br><span class="line">    	&#125;</span><br><span class="line">    &#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 了解v-on:为事件绑定的指令 --&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- methods为事件提供实现体--&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="4、computed：计算"><a href="#4、computed：计算" class="headerlink" title="4、computed：计算"></a>4、computed：计算</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line"> 	<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">v-model</span>=<span class="string">"a"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">v-model</span>=<span class="string">"b"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">        &#123;&#123; c &#125;&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="actionscript">	<span class="comment">// 一个变量依赖于多个变量</span></span></span><br><span class="line"><span class="actionscript">    <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">        el: <span class="string">"#app"</span>,</span></span><br><span class="line">        data: &#123;</span><br><span class="line"><span class="actionscript">            a: <span class="string">""</span>,</span></span><br><span class="line"><span class="actionscript">            b: <span class="string">""</span>,</span></span><br><span class="line">        &#125;,</span><br><span class="line">        computed: &#123;</span><br><span class="line"><span class="actionscript">            c: <span class="function"><span class="keyword">function</span><span class="params">()</span> </span>&#123;</span></span><br><span class="line"><span class="actionscript">                <span class="comment">// this代表该vue实例</span></span></span><br><span class="line"><span class="actionscript">                <span class="keyword">return</span> <span class="keyword">this</span>.a + <span class="keyword">this</span>.b;</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="5、watch：监听"><a href="#5、watch：监听" class="headerlink" title="5、watch：监听"></a>5、watch：监听</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line"> 	<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">v-model</span>=<span class="string">"ab"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">        &#123;&#123; a &#125;&#125;</span><br><span class="line">        &#123;&#123; b &#125;&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="actionscript">	<span class="comment">// 多个变量依赖于一个变量</span></span></span><br><span class="line"><span class="actionscript">    <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">        el: <span class="string">"#app"</span>,</span></span><br><span class="line">        data: &#123;</span><br><span class="line"><span class="actionscript">            ab: <span class="string">""</span>,</span></span><br><span class="line"><span class="actionscript">            a: <span class="string">""</span>,</span></span><br><span class="line"><span class="actionscript">            b: <span class="string">""</span>,</span></span><br><span class="line">        &#125;,</span><br><span class="line">        watch: &#123;</span><br><span class="line"><span class="actionscript">            ab: <span class="function"><span class="keyword">function</span><span class="params">()</span> </span>&#123;</span></span><br><span class="line"><span class="actionscript">                <span class="comment">// 逻辑根据需求而定</span></span></span><br><span class="line"><span class="actionscript">                <span class="keyword">this</span>.a = <span class="keyword">this</span>.ab[<span class="number">0</span>];</span></span><br><span class="line"><span class="actionscript">                <span class="keyword">this</span>.b = <span class="keyword">this</span>.ab[<span class="number">1</span>];</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="6、delimiters：分隔符"><a href="#6、delimiters：分隔符" class="headerlink" title="6、delimiters：分隔符"></a>6、delimiters：分隔符</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">'app'</span>&gt;</span></span><br><span class="line">    $&#123; msg &#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="actionscript">    <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">    	el: <span class="string">'#app'</span>,</span></span><br><span class="line">    	data: &#123;</span><br><span class="line"><span class="actionscript">    		msg: <span class="string">'message'</span></span></span><br><span class="line">    	&#125;,</span><br><span class="line"><span class="actionscript">        delimiters: [<span class="string">'$&#123;'</span>, <span class="string">'&#125;'</span>]</span></span><br><span class="line">    &#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>



<h2 id="三、生命周期钩子"><a href="#三、生命周期钩子" class="headerlink" title="三、生命周期钩子"></a>三、<a href="https://cn.vuejs.org/v2/api/#%E9%80%89%E9%A1%B9-%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E9%92%A9%E5%AD%90" target="_blank" rel="noopener">生命周期钩子</a></h2><ul>
<li>表示一个vue实例从创建到销毁的这个过程,将这个过程的一些时间节点赋予了对应的钩子函数</li>
<li>钩子函数: 满足特点条件被回调的方法</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> Vue(&#123;</span><br><span class="line">    el: <span class="string">"#app"</span>,</span><br><span class="line">    data: &#123;</span><br><span class="line">        msg: <span class="string">"message"</span></span><br><span class="line">    &#125;,</span><br><span class="line">    beforeCreate () &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"实例刚刚创建"</span>);</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="keyword">this</span>.msg</span><br><span class="line">                    </span><br><span class="line">    &#125;,</span><br><span class="line">    created () &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"实例创建成功, data, methods已拥有"</span>);</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="keyword">this</span>.msg);</span><br><span class="line">    &#125;,</span><br><span class="line">    mounted () &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"页面已被vue实例渲染, data, methods已更新"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 拿到需求 =&gt; 确定钩子函数 =&gt; 解决需求的逻辑代码块</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>



<h2 id="四、Vue指令"><a href="#四、Vue指令" class="headerlink" title="四、Vue指令"></a>四、Vue指令</h2><h4 id="1、文本相关指令"><a href="#1、文本相关指令" class="headerlink" title="1、文本相关指令"></a>1、文本相关指令</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 插值表达式 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; msg &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- eg:原文本会被msg替换 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span> <span class="attr">v-text</span>=<span class="string">'msg'</span>&gt;</span>原文本<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 可以解析带html标签的文本信息 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span> <span class="attr">v-html</span>=<span class="string">'msg'</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- v-once控制的标签只能被赋值一次 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span> <span class="attr">v-once</span>&gt;</span>&#123;&#123; msg &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span></span><br><span class="line"><span class="actionscript">	<span class="comment">// 指令: 出现在html标签中可以被vue解析处理的全局属性</span></span></span><br><span class="line"><span class="actionscript">	<span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">		el: <span class="string">"#app"</span>,</span></span><br><span class="line">		data: &#123;</span><br><span class="line"><span class="actionscript">			msg: <span class="string">"message"</span></span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="2、斗篷指令"><a href="#2、斗篷指令" class="headerlink" title="2、斗篷指令"></a>2、斗篷指令</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">"text/css"</span>&gt;</span></span><br><span class="line"><span class="css">    <span class="selector-attr">[v-cloak]</span> &#123; <span class="attribute">display</span>: none; &#125;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span> <span class="attr">v-cloak</span>&gt;</span></span><br><span class="line">    &#123;&#123; msg &#125;&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"js/vue.min.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span></span><br><span class="line"><span class="actionscript">	<span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">		el: <span class="string">"#app"</span>,</span></span><br><span class="line">		data: &#123;</span><br><span class="line"><span class="actionscript">			msg: <span class="string">"message"</span></span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 避免页面闪烁--&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="3、属性指令"><a href="#3、属性指令" class="headerlink" title="3、属性指令"></a>3、属性指令</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 给自定义全局属性绑定变量 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">v-bind:abc</span>=<span class="string">"abc"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 以原字符串形式绑定全局属性 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">v-bind:title</span>=<span class="string">"'abc'"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 单类名绑定 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">v-bind:class</span>=<span class="string">"c1"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 多类名绑定 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">v-bind:class</span>=<span class="string">"[c2, c3]"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 类名状态绑定 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">v-bind:class</span>=<span class="string">"&#123;c4: true|false|var&#125;"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 多类名状态绑定 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">v-bind:class</span>=<span class="string">"[&#123;c5: true&#125;, &#123;c6: flase&#125;]"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 样式绑定 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">:style</span>=<span class="string">"div_style"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">:style</span>=<span class="string">"&#123;width: '100px', height: '100px', backgroundColor: 'blue'&#125;"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span></span><br><span class="line"><span class="actionscript">	<span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">		el:<span class="string">"#app"</span>,</span></span><br><span class="line">		data: &#123;</span><br><span class="line"><span class="actionscript">            abc: <span class="string">"abc"</span>,</span></span><br><span class="line"><span class="actionscript">            c1: <span class="string">"p1"</span>,</span></span><br><span class="line"><span class="actionscript">            c2: <span class="string">"p2"</span>,</span></span><br><span class="line"><span class="actionscript">            c3: <span class="string">"p3"</span>,</span></span><br><span class="line">			div_style: &#123;</span><br><span class="line"><span class="actionscript">				width: <span class="string">"200px"</span>,</span></span><br><span class="line"><span class="actionscript">				height: <span class="string">"200px"</span>,</span></span><br><span class="line"><span class="actionscript">				backgroundColor: <span class="string">"cyan"</span></span></span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- v-bind: 指令可以简写为 : --&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="4、事件指令"><a href="#4、事件指令" class="headerlink" title="4、事件指令"></a>4、事件指令</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- v-on: 指令 简写 @ --&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 不传参事件绑定，但事件回调方法可以获取事件对象 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> @<span class="attr">click</span>=<span class="string">"fn"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- ()可以传入具体实参 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> @<span class="attr">click</span>=<span class="string">"fn()"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- ()情况下，事件对象应该显式传入 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> @<span class="attr">click</span>=<span class="string">"fn($event)"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="5、表单指令"><a href="#5、表单指令" class="headerlink" title="5、表单指令"></a>5、表单指令</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- v-model针对于表单元素 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">""</span> <span class="attr">method</span>=<span class="string">"get"</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 1、双向绑定：服务于文本输入框 --&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- v-model存储的值为输入框的value值 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">name</span>=<span class="string">"usr"</span> <span class="attr">v-model</span>=<span class="string">"in_val"</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"password"</span> <span class="attr">name</span>=<span class="string">"ps"</span> <span class="attr">v-model</span>=<span class="string">"in_val"</span> &gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">textarea</span> <span class="attr">name</span>=<span class="string">"info"</span> <span class="attr">v-model</span>=<span class="string">"in_val"</span>&gt;</span><span class="tag">&lt;/<span class="name">textarea</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 2、单选框 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="comment">&lt;!-- 单选框是以name进行分组，同组中只能发生单选 --&gt;</span></span><br><span class="line">            <span class="comment">&lt;!-- v-model存储的值为单选框的value值 --&gt;</span></span><br><span class="line">            男：<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"radio"</span> <span class="attr">name</span>=<span class="string">"sex"</span> <span class="attr">value</span>=<span class="string">"男"</span> <span class="attr">v-model</span>=<span class="string">"ra_val"</span>&gt;</span></span><br><span class="line">            女：<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"radio"</span> <span class="attr">name</span>=<span class="string">"sex"</span> <span class="attr">value</span>=<span class="string">"女"</span> <span class="attr">v-model</span>=<span class="string">"ra_val"</span>&gt;</span></span><br><span class="line">            &#123;&#123; ra_val &#125;&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 3、单一复选框 --&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- v-model存储的值为true|false --&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 或者为自定义替换的值 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">v-model</span>=<span class="string">'sin_val'</span> <span class="attr">true-value</span>=<span class="string">"选中"</span> <span class="attr">false-value</span>=<span class="string">"未选中"</span> /&gt;</span></span><br><span class="line">            &#123;&#123; sin_val &#125;&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 4、多复选框 --&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- v-model存储的值为存储值多复选框value的数组 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">value</span>=<span class="string">"喜好男的"</span> <span class="attr">name</span>=<span class="string">"cless"</span> <span class="attr">v-model</span>=<span class="string">'more_val'</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">value</span>=<span class="string">"喜好女的"</span> <span class="attr">name</span>=<span class="string">"cless"</span> <span class="attr">v-model</span>=<span class="string">'more_val'</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">value</span>=<span class="string">"不挑"</span> <span class="attr">name</span>=<span class="string">"cless"</span> <span class="attr">v-model</span>=<span class="string">'more_val'</span> /&gt;</span></span><br><span class="line">            &#123;&#123; more_val &#125;&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span></span><br><span class="line"><span class="actionscript">	<span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">		el: <span class="string">'#app'</span>,</span></span><br><span class="line">		data: &#123;</span><br><span class="line"><span class="actionscript">			in_val: <span class="string">''</span>,</span></span><br><span class="line"><span class="actionscript">			<span class="comment">// 默认值可以决定单选框默认选项</span></span></span><br><span class="line"><span class="actionscript">			ra_val: <span class="string">'男'</span>,</span></span><br><span class="line"><span class="actionscript">			<span class="comment">// 默认值为true，单一复选框为选中，反之false为不选中</span></span></span><br><span class="line"><span class="actionscript">			sin_val: <span class="string">''</span>,</span></span><br><span class="line"><span class="actionscript">			<span class="comment">// 数组中存在的值对应的复选框默认为选中状态</span></span></span><br><span class="line"><span class="actionscript">			more_val: [<span class="string">'喜好女的'</span>,<span class="string">'不挑'</span>]</span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="6、条件指令"><a href="#6、条件指令" class="headerlink" title="6、条件指令"></a>6、条件指令</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"toggle"</span>&gt;</span>显隐切换<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- v-if --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"box r"</span> <span class="attr">v-if</span>=<span class="string">"isShow"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- v-show --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"box o"</span> <span class="attr">v-show</span>=<span class="string">"isShow"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 1.条件渲染的值为true|false --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 2.true代表标签显示方式渲染 --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 3.false v-if不渲染到页面,v-show以display:none渲染到页面,但也不会显示 --&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- v-if v-else-if v-else 案例 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> @<span class="attr">mouseover</span>=<span class="string">"changeWrap(0)"</span>&gt;</span>red<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> @<span class="attr">mouseover</span>=<span class="string">"changeWrap(1)"</span>&gt;</span>green<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> @<span class="attr">mouseover</span>=<span class="string">"changeWrap(2)"</span>&gt;</span>blue<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- red页面逻辑结构 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"wrap red"</span> <span class="attr">v-if</span>=<span class="string">"tag == 0"</span> <span class="attr">key</span>=<span class="string">"0"</span>&gt;</span>...<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- green页面逻辑结构 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"wrap green"</span> <span class="attr">v-else-if</span>=<span class="string">"tag == 1"</span> <span class="attr">key</span>=<span class="string">"1"</span>&gt;</span>...<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- blue页面逻辑结构 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"wrap blue"</span> <span class="attr">v-else</span> <span class="attr">key</span>=<span class="string">"2"</span>&gt;</span>...<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- v-if相关分支操作,在未显示情况下,是不会被渲染到页面中 --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 通过key全局属性操作后,渲染过的分支会建立key对应的缓存,提高下一次渲染速度 --&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- v-show 案例 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> @<span class="attr">mouseover</span>=<span class="string">"changeMain(0)"</span>&gt;</span>red<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> @<span class="attr">mouseover</span>=<span class="string">"changeMain(1)"</span>&gt;</span>green<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> @<span class="attr">mouseover</span>=<span class="string">"changeMain(2)"</span>&gt;</span>blue<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- red页面逻辑结构 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"main red"</span> <span class="attr">v-show</span>=<span class="string">"whoShow(0)"</span>&gt;</span>...<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- green页面逻辑结构 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"main green"</span> <span class="attr">v-show</span>=<span class="string">"whoShow(1)"</span>&gt;</span>...<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- blue页面逻辑结构 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"main blue"</span> <span class="attr">v-show</span>=<span class="string">"whoShow(2)"</span>&gt;</span>...<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span></span><br><span class="line"><span class="actionscript">	<span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">		el: <span class="string">"#app"</span>,</span></span><br><span class="line">		data: &#123;</span><br><span class="line"><span class="actionscript">			isShow: <span class="literal">false</span>,</span></span><br><span class="line">			tag: 0,</span><br><span class="line">			flag: 0</span><br><span class="line">		&#125;,</span><br><span class="line">		methods: &#123;</span><br><span class="line">			toggle () &#123;</span><br><span class="line"><span class="actionscript">				<span class="keyword">this</span>.isShow = !<span class="keyword">this</span>.isShow;</span></span><br><span class="line">			&#125;,</span><br><span class="line">			changeWrap (num) &#123;</span><br><span class="line"><span class="actionscript">				<span class="keyword">this</span>.tag = num;</span></span><br><span class="line">			&#125;,</span><br><span class="line">			changeMain (num) &#123;</span><br><span class="line"><span class="actionscript">				<span class="comment">// this.flag num</span></span></span><br><span class="line"><span class="actionscript">				<span class="keyword">this</span>.flag = num;</span></span><br><span class="line">			&#125;,</span><br><span class="line">			whoShow (num) &#123;</span><br><span class="line"><span class="actionscript">				<span class="comment">// this.flag num</span></span></span><br><span class="line"><span class="actionscript">				<span class="keyword">return</span> <span class="keyword">this</span>.flag == num;</span></span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="7、循环指令"><a href="#7、循环指令" class="headerlink" title="7、循环指令"></a>7、循环指令</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h1</span>&gt;</span>&#123;&#123; msg &#125;&#125;<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- v-for="item in items" --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 遍历的对象: 数组[] 对象(字典)&#123;&#125; --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span>&gt;</span>&#123;&#123; list[0] &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span>&gt;</span>&#123;&#123; list[1] &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span>&gt;</span>&#123;&#123; list[2] &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span>&gt;</span>&#123;&#123; list[3] &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span>&gt;</span>&#123;&#123; list[4] &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- n为遍历的元素值 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">"n in list"</span>&gt;</span>&#123;&#123; n &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 一般列表渲染需要建立缓存 --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 列表渲染是循环,需要赋值变量给key,使用key需要v-bind:处理 --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- v-for变量数组[]时,接收两个值时,第一个为元素值,第二个为元素索引 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">"(n, i) in list"</span> <span class="attr">:key</span>=<span class="string">"i"</span>&gt;</span>value:&#123;&#123; n &#125;&#125; | index: &#123;&#123; i &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span>&gt;</span>&#123;&#123; dic['name'] &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span>&gt;</span>&#123;&#123; dic.age &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span>&gt;</span>&#123;&#123; dic.gender &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- v-for变量对象&#123;&#125;时,接收三个值时,第一个为元素值,第二个为元素键,第三个为元素索引 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">"(v, k, i) in dic"</span> <span class="attr">:key</span>=<span class="string">"k"</span>&gt;</span>value:&#123;&#123; v &#125;&#125; | key:&#123;&#123; k &#125;&#125; | index: &#123;&#123; i &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 遍历的嵌套 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">v-for</span>=<span class="string">"(person, index) in persons"</span> <span class="attr">:key</span>=<span class="string">"index"</span> <span class="attr">style</span>=<span class="string">"height: 21px;"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">v-for</span>=<span class="string">"(v, k) in person"</span> <span class="attr">:key</span>=<span class="string">"k"</span> <span class="attr">style</span>=<span class="string">"float: left;"</span>&gt;</span>&#123;&#123; k &#125;&#125; : &#123;&#123; v &#125;&#125;<span class="symbol">&amp;nbsp;</span><span class="symbol">&amp;nbsp;</span><span class="symbol">&amp;nbsp;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span></span><br><span class="line"><span class="actionscript">	<span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">		el: <span class="string">"#app"</span>,</span></span><br><span class="line">		data: &#123;</span><br><span class="line"><span class="actionscript">			msg: <span class="string">"列表渲染"</span>,</span></span><br><span class="line">			list: [1, 2, 3, 4, 5],</span><br><span class="line">			dic: &#123;</span><br><span class="line"><span class="actionscript">				name: <span class="string">'zero'</span>,</span></span><br><span class="line">				age: 88888,</span><br><span class="line"><span class="actionscript">				gender: <span class="string">'god'</span></span></span><br><span class="line">			&#125;,</span><br><span class="line">			persons: [</span><br><span class="line"><span class="actionscript">				&#123;name: <span class="string">"zero"</span>, age: <span class="number">8</span>&#125;,</span></span><br><span class="line"><span class="actionscript">				&#123;name: <span class="string">"egon"</span>, age: <span class="number">78</span>&#125;,</span></span><br><span class="line"><span class="actionscript">				&#123;name: <span class="string">"liuXX"</span>, age: <span class="number">77</span>&#125;,</span></span><br><span class="line"><span class="actionscript">				&#123;name: <span class="string">"yXX"</span>, age: <span class="number">38</span>&#125;</span></span><br><span class="line">			]</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="8、todolist案例"><a href="#8、todolist案例" class="headerlink" title="8、todolist案例"></a>8、todolist案例</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">v-model</span>=<span class="string">"val"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">"button"</span> @<span class="attr">click</span>=<span class="string">"submitMsg"</span>&gt;</span>提交<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">"(v, i) in list"</span> <span class="attr">:key</span>=<span class="string">"i"</span> @<span class="attr">click</span>=<span class="string">"removeMsg(i)"</span>&gt;</span>&#123;&#123; v &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line">    &#123;&#123; list &#125;&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span></span><br><span class="line"><span class="actionscript">	<span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">		el: <span class="string">"#app"</span>,</span></span><br><span class="line">		data: &#123;</span><br><span class="line"><span class="actionscript">			val: <span class="string">""</span>,</span></span><br><span class="line">			list: []</span><br><span class="line">		&#125;,</span><br><span class="line">		methods: &#123;</span><br><span class="line">			submitMsg () &#123;</span><br><span class="line"><span class="actionscript">				<span class="keyword">if</span> (<span class="keyword">this</span>.val) &#123;</span></span><br><span class="line"><span class="actionscript">					<span class="keyword">this</span>.list.push(<span class="keyword">this</span>.val);</span></span><br><span class="line"><span class="actionscript">					<span class="keyword">this</span>.val = <span class="string">""</span></span></span><br><span class="line">				&#125;</span><br><span class="line">			&#125;,</span><br><span class="line">			removeMsg(index) &#123;</span><br><span class="line"><span class="actionscript">				<span class="keyword">this</span>.list.splice(index, <span class="number">1</span>)</span></span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>



<h2 id="五、组件"><a href="#五、组件" class="headerlink" title="五、组件"></a>五、组件</h2><ul>
<li>每一个组件都是一个vue实例</li>
<li>每个组件均具有自身的模板template，根组件的模板就是挂载点</li>
<li>每个组件模板只能拥有一个根标签</li>
<li>子组件的数据具有作用域，以达到组件的复用</li>
</ul>
<h4 id="1、根组件"><a href="#1、根组件" class="headerlink" title="1、根组件"></a>1、根组件</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h1</span>&gt;</span>&#123;&#123; msg &#125;&#125;<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span></span><br><span class="line"><span class="actionscript">	<span class="comment">// 通过new Vue创建的实例就是根组件(实例与组件一一对应,一个实例就是一个组件)</span></span></span><br><span class="line"><span class="actionscript">	<span class="comment">// 每个组件组件均拥有模板,template</span></span></span><br><span class="line"><span class="actionscript">	<span class="keyword">var</span> app = <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">		<span class="comment">// 根组件的模板就是挂载点</span></span></span><br><span class="line"><span class="actionscript">		el: <span class="string">"#app"</span>,</span></span><br><span class="line">		data : &#123;</span><br><span class="line"><span class="actionscript">			msg: <span class="string">"根组件"</span></span></span><br><span class="line">		&#125;,</span><br><span class="line"><span class="actionscript">		<span class="comment">// 模板: 由""包裹的html代码块,出现在组件的内部,赋值给组件的$template变量</span></span></span><br><span class="line"><span class="actionscript">		<span class="comment">// 显式书写模块,就会替换挂载点,但根组件必须拥有挂载点</span></span></span><br><span class="line"><span class="handlebars"><span class="xml">		template: "<span class="tag">&lt;<span class="name">div</span>&gt;</span>显式模板<span class="tag">&lt;/<span class="name">div</span>&gt;</span>"</span></span></span><br><span class="line">	&#125;)</span><br><span class="line"><span class="actionscript">	<span class="comment">// app.$template</span></span></span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="2、局部组件"><a href="#2、局部组件" class="headerlink" title="2、局部组件"></a>2、局部组件</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">local-tag</span>&gt;</span><span class="tag">&lt;/<span class="name">local-tag</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">local-tag</span>&gt;</span><span class="tag">&lt;/<span class="name">local-tag</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="actionscript">    <span class="keyword">var</span> localTag = &#123;</span></span><br><span class="line">        data () &#123;</span><br><span class="line"><span class="actionscript">            <span class="keyword">return</span> &#123;</span></span><br><span class="line">                count: 0</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;,</span><br><span class="line"><span class="handlebars"><span class="xml">        template: '<span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"btnAction"</span>&gt;</span>局部</span><span class="template-variable">&#123;&#123; count &#125;&#125;</span><span class="xml"><span class="tag">&lt;/<span class="name">button</span>&gt;</span>',</span></span></span><br><span class="line">        methods: &#123;</span><br><span class="line">            btnAction () &#123;</span><br><span class="line"><span class="actionscript">                <span class="keyword">this</span>.count ++</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="actionscript">    <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">        el: <span class="string">"#app"</span>,</span></span><br><span class="line">        components: &#123;</span><br><span class="line"><span class="actionscript">            <span class="string">'local-tag'</span>: localTag</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="3、全局组件"><a href="#3、全局组件" class="headerlink" title="3、全局组件"></a>3、全局组件</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">global-tag</span>&gt;</span><span class="tag">&lt;/<span class="name">global-tag</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">global-tag</span>&gt;</span><span class="tag">&lt;/<span class="name">global-tag</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="actionscript">	Vue.component(<span class="string">'global-tag'</span>, &#123;</span></span><br><span class="line">		data () &#123;</span><br><span class="line"><span class="actionscript">			<span class="keyword">return</span> &#123;</span></span><br><span class="line">				count: 0</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;,</span><br><span class="line"><span class="handlebars"><span class="xml">		template: '<span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"btnAction"</span>&gt;</span>全局</span><span class="template-variable">&#123;&#123; count &#125;&#125;</span><span class="xml"><span class="tag">&lt;/<span class="name">button</span>&gt;</span>',</span></span></span><br><span class="line">		methods: &#123;</span><br><span class="line">			btnAction () &#123;</span><br><span class="line"><span class="actionscript">				<span class="keyword">this</span>.count ++</span></span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line"><span class="actionscript">    <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">        el: <span class="string">"#app"</span></span></span><br><span class="line">    &#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="4、父组件传递数据给子组件"><a href="#4、父组件传递数据给子组件" class="headerlink" title="4、父组件传递数据给子组件"></a>4、父组件传递数据给子组件</h4><ul>
<li>通过绑定属性的方式进行数据传递</li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">global-tag</span> <span class="attr">:sup_data1</span>=<span class="string">'sup_data1'</span> <span class="attr">:supData2</span>=<span class="string">'sup_data2'</span>&gt;</span><span class="tag">&lt;/<span class="name">global-tag</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span></span><br><span class="line"><span class="actionscript">	Vue.component(<span class="string">'global-tag'</span>, &#123;</span></span><br><span class="line"><span class="actionscript">		props:[<span class="string">'sup_data1'</span>, <span class="string">'supdata2'</span>],</span></span><br><span class="line"><span class="handlebars"><span class="xml">		template: '<span class="tag">&lt;<span class="name">div</span>&gt;</span></span><span class="template-variable">&#123;&#123; sup_data1 &#125;&#125;</span><span class="xml"> </span><span class="template-variable">&#123;&#123; supdata2 &#125;&#125;</span><span class="xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span>'</span></span></span><br><span class="line">	&#125;)</span><br><span class="line"><span class="actionscript">	<span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">		el: <span class="string">'#app'</span>,</span></span><br><span class="line">		data: &#123;</span><br><span class="line"><span class="actionscript">			sup_data1: <span class="string">'数据1'</span>,</span></span><br><span class="line"><span class="actionscript">			sup_data2: <span class="string">'数据2'</span></span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="5、子组件传递数据给父组件"><a href="#5、子组件传递数据给父组件" class="headerlink" title="5、子组件传递数据给父组件"></a>5、子组件传递数据给父组件</h4><ul>
<li>通过发送事件请求的方式进行数据传递</li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">global-tag</span> @<span class="attr">send_action</span>=<span class="string">'receiveAction'</span>&gt;</span><span class="tag">&lt;/<span class="name">global-tag</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span></span><br><span class="line"><span class="actionscript">	Vue.component(<span class="string">'global-tag'</span>, &#123;</span></span><br><span class="line">		data () &#123;</span><br><span class="line"><span class="actionscript">			<span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="actionscript">				sub_data1: <span class="string">"数据1"</span>,</span></span><br><span class="line"><span class="actionscript">				sub_data2: <span class="string">'数据2'</span></span></span><br><span class="line">			&#125;</span><br><span class="line">		&#125;,</span><br><span class="line"><span class="handlebars"><span class="xml">		template: '<span class="tag">&lt;<span class="name">div</span> @<span class="attr">click</span>=<span class="string">"clickAction"</span>&gt;</span>发生<span class="tag">&lt;/<span class="name">div</span>&gt;</span>',</span></span></span><br><span class="line">		methods: &#123;</span><br><span class="line">			clickAction () &#123;</span><br><span class="line"><span class="actionscript">				<span class="keyword">this</span>.$emit(<span class="string">'send_action'</span>, <span class="keyword">this</span>.sub_data1, <span class="keyword">this</span>.sub_data2)</span></span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line"><span class="actionscript">	<span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">		el: <span class="string">'#app'</span>,</span></span><br><span class="line">		methods: &#123;</span><br><span class="line">			receiveAction (v1, v2) &#123;</span><br><span class="line"><span class="javascript">				<span class="built_in">console</span>.log(v1, v2)</span></span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="6、父子组件实现todoList"><a href="#6、父子组件实现todoList" class="headerlink" title="6、父子组件实现todoList"></a>6、父子组件实现todoList</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">v-model</span>=<span class="string">"val"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">"button"</span> @<span class="attr">click</span>=<span class="string">"submitMsg"</span>&gt;</span>提交<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- &lt;li v-for="(v, i) in list" :key="i" @click="removeMsg(i)"&gt;&#123;&#123; v &#125;&#125;&lt;/li&gt; --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">todo-list</span> <span class="attr">v-for</span>=<span class="string">"(v, i) in list"</span> <span class="attr">:key</span>=<span class="string">"i"</span> <span class="attr">:v</span>=<span class="string">"v"</span> <span class="attr">:i</span>=<span class="string">"i"</span> @<span class="attr">delect_action</span>=<span class="string">"delect_action"</span>&gt;</span><span class="tag">&lt;/<span class="name">todo-list</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span></span><br><span class="line"><span class="actionscript">	Vue.component(<span class="string">"todo-list"</span>, &#123;</span></span><br><span class="line"><span class="handlebars"><span class="xml">		template: "<span class="tag">&lt;<span class="name">li</span> @<span class="attr">click</span>=<span class="string">'delect_action'</span>&gt;</span><span class="tag">&lt;<span class="name">span</span>&gt;</span>第</span><span class="template-variable">&#123;&#123; i + 1 &#125;&#125;</span><span class="xml">条: <span class="tag">&lt;/<span class="name">span</span>&gt;</span><span class="tag">&lt;<span class="name">span</span>&gt;</span></span><span class="template-variable">&#123;&#123; v &#125;&#125;</span><span class="xml"><span class="tag">&lt;/<span class="name">span</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span>",</span></span></span><br><span class="line"><span class="actionscript">		props: [<span class="string">'v'</span>, <span class="string">'i'</span>],</span></span><br><span class="line">		methods: &#123;</span><br><span class="line">			delect_action () &#123;</span><br><span class="line"><span class="actionscript">				<span class="keyword">this</span>.$emit(<span class="string">"delect_action"</span>, <span class="keyword">this</span>.i)</span></span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line">	</span><br><span class="line"><span class="actionscript">	<span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="actionscript">		el: <span class="string">"#app"</span>,</span></span><br><span class="line">		data: &#123;</span><br><span class="line"><span class="actionscript">			val: <span class="string">""</span>,</span></span><br><span class="line">			list: []</span><br><span class="line">		&#125;,</span><br><span class="line">		methods: &#123;</span><br><span class="line">			submitMsg () &#123;</span><br><span class="line"><span class="actionscript">				<span class="comment">// 往list中添加input框中的value</span></span></span><br><span class="line"><span class="actionscript">				<span class="keyword">if</span> (<span class="keyword">this</span>.val) &#123;</span></span><br><span class="line"><span class="actionscript">					<span class="keyword">this</span>.list.push(<span class="keyword">this</span>.val);</span></span><br><span class="line"><span class="actionscript">					<span class="keyword">this</span>.val = <span class="string">""</span></span></span><br><span class="line">				&#125;</span><br><span class="line">			&#125;,</span><br><span class="line">			delect_action(index) &#123;</span><br><span class="line"><span class="actionscript">				<span class="keyword">this</span>.list.splice(index, <span class="number">1</span>)</span></span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>



<h2 id="六、Vue-CLI-项目搭建"><a href="#六、Vue-CLI-项目搭建" class="headerlink" title="六、Vue-CLI 项目搭建"></a>六、Vue-CLI 项目搭建</h2><h4 id="1、环境搭建"><a href="#1、环境搭建" class="headerlink" title="1、环境搭建"></a>1、环境搭建</h4><ul>
<li>安装node</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">官网下载安装包，傻瓜式安装：https:&#x2F;&#x2F;nodejs.org&#x2F;zh-cn&#x2F;</span><br></pre></td></tr></table></figure>

<ul>
<li>安装cnpm</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g cnpm --registry&#x3D;https:&#x2F;&#x2F;registry.npm.taobao.org</span><br></pre></td></tr></table></figure>

<ul>
<li>安装脚手架</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cnpm install -g @vue&#x2F;cli</span><br></pre></td></tr></table></figure>

<ul>
<li>清空缓存处理</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm cache clean --force</span><br></pre></td></tr></table></figure>

<h4 id="2、项目的创建"><a href="#2、项目的创建" class="headerlink" title="2、项目的创建"></a>2、项目的创建</h4><ul>
<li>创建项目</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">vue creat 项目名</span><br><span class="line"><span class="comment">// 要提前进入目标目录(项目应该创建在哪个目录下)</span></span><br><span class="line"><span class="comment">// 选择自定义方式创建项目，选取Router, Vuex插件</span></span><br></pre></td></tr></table></figure>

<ul>
<li>启动/停止项目</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm run serve / ctrl+c</span><br><span class="line"><span class="comment">// 要提前进入项目根目录</span></span><br></pre></td></tr></table></figure>

<ul>
<li>打包项目</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm run build</span><br><span class="line"><span class="comment">// 要在项目根目录下进行打包操作</span></span><br></pre></td></tr></table></figure>

<h4 id="3、认识项目"><a href="#3、认识项目" class="headerlink" title="3、认识项目"></a>3、认识项目</h4><ul>
<li>项目目录</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">dist: 打包的项目目录(打包后会生成)</span><br><span class="line">node_modules: 项目依赖</span><br><span class="line">public: 共用资源</span><br><span class="line">src: 项目目标,书写代码的地方</span><br><span class="line">	-- assets:资源</span><br><span class="line">	-- components:组件</span><br><span class="line">	-- views:视图组件</span><br><span class="line">	-- App.vue:根组件</span><br><span class="line">	-- main.js: 入口js</span><br><span class="line">	-- router.js: 路由文件</span><br><span class="line">	-- store.js: 状态库文件</span><br><span class="line">vue.config.js: 项目配置文件(没有可以自己新建)</span><br></pre></td></tr></table></figure>

<ul>
<li>配置文件：vue.config.js</li>
</ul>
<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports=&#123;</span><br><span class="line">	devServer: &#123;</span><br><span class="line">		port: <span class="number">8888</span></span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 修改端口,选做</span></span><br></pre></td></tr></table></figure>

<ul>
<li>main.js</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> Vue(&#123;</span><br><span class="line">	el: <span class="string">"#app"</span>,</span><br><span class="line">	router: router,</span><br><span class="line">	store: store,</span><br><span class="line">	render: <span class="function"><span class="keyword">function</span> (<span class="params">h</span>) </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> h(App)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<ul>
<li>.vue文件</li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 模板区域 --&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="actionscript">    <span class="comment">// 逻辑代码区域</span></span></span><br><span class="line"><span class="actionscript">    <span class="comment">// 该语法和script绑定出现</span></span></span><br><span class="line"><span class="javascript">    <span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line">        </span><br><span class="line">    &#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span> <span class="attr">scoped</span>&gt;</span></span><br><span class="line"><span class="css">    <span class="comment">/* 样式区域 */</span></span></span><br><span class="line"><span class="css">    <span class="comment">/* scoped表示这里的样式只适用于组件内部, scoped与style绑定出现 */</span></span></span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="4、项目功能"><a href="#4、项目功能" class="headerlink" title="4、项目功能"></a>4、项目功能</h4><ul>
<li>vue-router</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    path: <span class="string">'/'</span>,</span><br><span class="line">    name: <span class="string">'home'</span>,</span><br><span class="line">    <span class="comment">// 路由的重定向</span></span><br><span class="line">    redirect: <span class="string">'/home'</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// 一级路由, 在根组件中被渲染, 替换根组件的&lt;router-view/&gt;标签</span></span><br><span class="line">    path: <span class="string">'/one-view'</span>,</span><br><span class="line">    name: <span class="string">'one'</span>,</span><br><span class="line">    component: <span class="function"><span class="params">()</span> =&gt;</span> <span class="keyword">import</span>(<span class="string">'./views/OneView.vue'</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// 多级路由, 在根组件中被渲染, 替换根组件的&lt;router-view/&gt;标签</span></span><br><span class="line">    path: <span class="string">'/one-view/one-detail'</span>,</span><br><span class="line">    component: <span class="function"><span class="params">()</span> =&gt;</span> <span class="keyword">import</span>(<span class="string">'./views/OneDetail.vue'</span>),</span><br><span class="line">    <span class="comment">// 子路由, 在所属路由指向的组件中被渲染, 替换该组件(OneDetail)的&lt;router-view/&gt;标签</span></span><br><span class="line">    children: [&#123;</span><br><span class="line">        path: <span class="string">'show'</span>,</span><br><span class="line">        component: <span class="function"><span class="params">()</span> =&gt;</span> <span class="keyword">import</span>(<span class="string">'./components/OneShow.vue'</span>)</span><br><span class="line">    &#125;]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- router-link渲染为a标签 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">"/"</span>&gt;</span>Home<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span> |</span><br><span class="line"><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">"/about"</span>&gt;</span>About<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span> |</span><br><span class="line"><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">:to</span>=<span class="string">"&#123;name: 'one'&#125;"</span>&gt;</span>One<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span> |</span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 为路由渲染的组件占位 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">router-view</span> /&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">a</span><span class="selector-class">.router-link-exact-active</span> &#123;</span><br><span class="line">    <span class="attribute">color</span>: <span class="number">#42b983</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// router的逻辑转跳</span></span><br><span class="line"><span class="keyword">this</span>.$router.push(<span class="string">'/one-view'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// router采用history方式访问上一级</span></span><br><span class="line"><span class="keyword">this</span>.$router.go(<span class="number">-1</span>)</span><br></pre></td></tr></table></figure>

<ul>
<li>vuex</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 在任何一个组件中,均可以通过this.$store.state.msg访问msg的数据</span></span><br><span class="line"><span class="comment">// state永远只能拥有一种状态值</span></span><br><span class="line">state: &#123;</span><br><span class="line">    msg: <span class="string">"状态管理器"</span></span><br><span class="line">&#125;,</span><br><span class="line"><span class="comment">// 让state拥有多个状态值</span></span><br><span class="line">mutations: &#123;</span><br><span class="line">    <span class="comment">// 在一个一个组件中,均可以通过this.$store.commit('setMsg', new_msg)来修改state中的msg</span></span><br><span class="line">    setMsg(state, new_msg) &#123;</span><br><span class="line">        state.msg = new_msg</span><br><span class="line">    &#125;</span><br><span class="line">&#125;,</span><br><span class="line"><span class="comment">// 让mutations拥有多个状态值</span></span><br><span class="line">actions: &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>vue-cookie</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 安装cookie的命令</span></span><br><span class="line"><span class="comment">// npm install vue-cookie --save</span></span><br><span class="line"><span class="comment">// 为项目配置全局vue-cookie</span></span><br><span class="line"><span class="keyword">import</span> VueCookie <span class="keyword">from</span> <span class="string">'vue-cookie'</span></span><br><span class="line"><span class="comment">// 将插件设置给Vue原型,作为全局的属性,在任何地方都可以通过this.$cookie进行访问</span></span><br><span class="line">Vue.prototype.$cookie = VueCookie</span><br></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 持久化存储val的值到cookie中</span></span><br><span class="line"><span class="keyword">this</span>.$cookie.set(<span class="string">'val'</span>, <span class="keyword">this</span>.val)</span><br><span class="line"><span class="comment">// 获取cookie中val字段值</span></span><br><span class="line"><span class="keyword">this</span>.$cookie.get(<span class="string">'val'</span>)</span><br></pre></td></tr></table></figure>

<ul>
<li>axios</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 安装 axios(ajax)的命令</span></span><br><span class="line"><span class="comment">// npm install axios--save</span></span><br><span class="line"><span class="comment">// 为项目配置全局axios</span></span><br><span class="line"><span class="keyword">import</span> Axios <span class="keyword">from</span> <span class="string">'axios'</span></span><br><span class="line">Vue.prototype.$ajax = Axios</span><br></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> _this = <span class="keyword">this</span></span><br><span class="line"><span class="keyword">this</span>.$ajax(&#123;</span><br><span class="line">    method: <span class="string">'post'</span>,</span><br><span class="line">    url: <span class="string">'http://127.0.0.1:5000/loginAction'</span>,</span><br><span class="line">    params: &#123;</span><br><span class="line">        usr: <span class="keyword">this</span>.usr,</span><br><span class="line">        ps: <span class="keyword">this</span>.ps</span><br><span class="line">    &#125;</span><br><span class="line">&#125;).then(<span class="function"><span class="keyword">function</span>(<span class="params">res</span>) </span>&#123;</span><br><span class="line">    <span class="comment">// this代表的是回调then这个方法的调用者(axios插件),也就是发生了this的重指向</span></span><br><span class="line">    <span class="comment">// 要更新页面的title变量,title属于vue实例</span></span><br><span class="line">    <span class="comment">// res为回调的对象,该对象的data属性就是后台返回的数据</span></span><br><span class="line">    _this.title = res.data</span><br><span class="line">&#125;).catch(<span class="function"><span class="keyword">function</span>(<span class="params">err</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">window</span>.console.log(err)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 用pycharm启动该文件模拟后台</span></span><br><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask, request, render_template</span><br><span class="line"><span class="keyword">from</span> flask_cors <span class="keyword">import</span> CORS</span><br><span class="line">app = Flask(__name__)</span><br><span class="line">CORS(app, supports_credentials=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route('/')</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span><span class="params">()</span>:</span></span><br><span class="line">    <span class="keyword">return</span> <span class="string">"&lt;h1&gt;主页&lt;/h1&gt;"</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route('/loginAction', methods=['GET', 'POST'])</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">test_action</span><span class="params">()</span>:</span></span><br><span class="line">    <span class="comment"># print(request.args)</span></span><br><span class="line">    <span class="comment"># print(request.form)</span></span><br><span class="line">    <span class="comment"># print(request.values)</span></span><br><span class="line">    usr = request.args[<span class="string">'usr'</span>]</span><br><span class="line">    ps = request.args[<span class="string">'ps'</span>]</span><br><span class="line">    <span class="keyword">if</span> usr != <span class="string">'abc'</span> <span class="keyword">or</span> ps != <span class="string">'123'</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="string">'login failed'</span></span><br><span class="line">    <span class="keyword">return</span> <span class="string">'login success'</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    app.run()</span><br></pre></td></tr></table></figure>

      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/blog/2020/02/28/Vue/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-Git与Github的连接与使用" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/02/28/Git%E4%B8%8EGithub%E7%9A%84%E8%BF%9E%E6%8E%A5%E4%B8%8E%E4%BD%BF%E7%94%A8/">Git与Github的连接与使用</a>
    </h1>
  

        
        <a href="/blog/2020/02/28/Git%E4%B8%8EGithub%E7%9A%84%E8%BF%9E%E6%8E%A5%E4%B8%8E%E4%BD%BF%E7%94%A8/" class="archive-article-date">
  	<time datetime="2020-02-28T04:26:32.543Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2020-02-28</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h1 id="Git与Github的连接与使用"><a href="#Git与Github的连接与使用" class="headerlink" title="Git与Github的连接与使用"></a>Git与Github的连接与使用</h1><h2 id="一-安装git软件"><a href="#一-安装git软件" class="headerlink" title="一 安装git软件"></a>一 安装git软件</h2><h3 id="1、git介绍"><a href="#1、git介绍" class="headerlink" title="1、git介绍"></a>1、git介绍</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">''' </span></span><br><span class="line"><span class="string">	git是一款免费、开源的分布式版本控制系统，用于敏捷高效地处理任何或小或大的项目。</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">	分布式相比于集中式的最大区别在于开发者可以提交到本地，每个开发者通过克隆（git clone），在本地机器上拷贝一个完整的Git仓库。</span></span><br><span class="line"><span class="string">'''</span></span><br></pre></td></tr></table></figure>



<h3 id="2、下载与安装"><a href="#2、下载与安装" class="headerlink" title="2、下载与安装"></a>2、下载与安装</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># windows:</span></span><br><span class="line">官网下载:</span><br><span class="line">    	https://git-scm.com/downloads</span><br><span class="line"></span><br><span class="line">国内镜像下载:</span><br><span class="line">    	https://github.com/waylau/git-<span class="keyword">for</span>-win</span><br><span class="line"></span><br><span class="line"><span class="comment"># mac：</span></span><br><span class="line">mac系统自带git客户端。</span><br></pre></td></tr></table></figure>

<h2 id="二-注册Github与码云并创建项目"><a href="#二-注册Github与码云并创建项目" class="headerlink" title="二 注册Github与码云并创建项目"></a>二 注册Github与码云并创建项目</h2><h3 id="github-https-github-com-login"><a href="#github-https-github-com-login" class="headerlink" title="github: https://github.com/login"></a>github: <a href="https://github.com/login" target="_blank" rel="noopener">https://github.com/login</a></h3><h3 id="码云-https-gitee-com-login"><a href="#码云-https-gitee-com-login" class="headerlink" title="码云: https://gitee.com/login"></a>码云: <a href="https://gitee.com/login" target="_blank" rel="noopener">https://gitee.com/login</a></h3><h2 id="三-git命令操作"><a href="#三-git命令操作" class="headerlink" title="三 git命令操作"></a>三 git命令操作</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 0.创建git本地仓库文件夹</span></span><br><span class="line">mkdir tank</span><br><span class="line">cd tank</span><br><span class="line"></span><br><span class="line"><span class="comment"># 1.初始化git</span></span><br><span class="line">git init</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2.创建SSH key</span></span><br><span class="line">ssh-keygen -t rsa -C <span class="string">"githu项目url.git"</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3.将你的ssh 秘钥key值赋值到剪贴板</span></span><br><span class="line">pbcopy &lt; /Users/tank/.ssh/id_rsa.pub</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4.把剪贴板的秘钥key值添加到github的SSH设置中</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 5.验证是否成功，在git bash里输入下面的命令</span></span><br><span class="line">ssh -T git@github.com  <span class="comment"># github</span></span><br><span class="line">ssh -T gitee@gitee.com  <span class="comment"># gitee</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 6.开始设置username和email</span></span><br><span class="line">git config --<span class="keyword">global</span> user.name  <span class="string">"name"</span>  <span class="comment"># 你的GitHub登陆名</span></span><br><span class="line">git config --<span class="keyword">global</span> user.email <span class="string">"1562*****660@126.com"</span>  <span class="comment"># 你的GitHub注册邮箱</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 7.创建git本地仓库文件夹</span></span><br><span class="line">mkdir spiders</span><br><span class="line"></span><br><span class="line"><span class="comment"># 8.查看仓库是否被修改</span></span><br><span class="line">git status</span><br><span class="line"></span><br><span class="line"><span class="comment"># 9.更新本地仓库</span></span><br><span class="line">git add .   <span class="comment"># 更改所有文件</span></span><br><span class="line">git commit -m <span class="string">"第一次更新"</span>  <span class="comment"># 给所有文件添加简介</span></span><br><span class="line">git commit -m <span class="string">"Git 爱之初体验"</span></span><br><span class="line"><span class="comment"># 10.查看项目SSH地址</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 11.开始关联远程仓库</span></span><br><span class="line"><span class="comment"># git remote add origin git@github.com:用户名/项目名.git </span></span><br><span class="line"><span class="string">'''</span></span><br><span class="line"><span class="string"><span class="meta">&gt;&gt;&gt; </span>git remote add origin git@github.com:TankJam/ATM.git</span></span><br><span class="line"><span class="string">'''</span></span><br><span class="line">git remote add origin git@gitee.com:kermitjam/git_demo2.git</span><br><span class="line"></span><br><span class="line"><span class="comment"># 12.上传本地仓库到GitHub中</span></span><br><span class="line"><span class="string">'''</span></span><br><span class="line"><span class="string"><span class="meta">&gt;&gt;&gt; </span>git push -u origin master</span></span><br><span class="line"><span class="string">'''</span></span><br></pre></td></tr></table></figure>




      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/blog/2020/02/28/Git%E4%B8%8EGithub%E7%9A%84%E8%BF%9E%E6%8E%A5%E4%B8%8E%E4%BD%BF%E7%94%A8/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-什么是微服务" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/01/11/%E4%BB%80%E4%B9%88%E6%98%AF%E5%BE%AE%E6%9C%8D%E5%8A%A1/">什么是微服务</a>
    </h1>
  

        
        <a href="/blog/2020/01/11/%E4%BB%80%E4%B9%88%E6%98%AF%E5%BE%AE%E6%9C%8D%E5%8A%A1/" class="archive-article-date">
  	<time datetime="2020-01-11T03:50:36.721Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2020-01-11</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>今年有人提出了2018年微服务将疯狂至死，可见微服务的争论从未停止过。在这我将自己对微服务的理解整理了一下，希望对大家有所帮助。</p>
<h1 id="1-什么是微服务"><a href="#1-什么是微服务" class="headerlink" title="1.什么是微服务"></a>1.什么是微服务</h1><p>1）一组小的服务（大小没有特别的标准，只要同一团队的工程师理解服务的标识一致即可）</p>
<p>2）独立的进程（java的tomcat，nodejs等）</p>
<p>3）轻量级的通信（不是soap，是http协议）</p>
<p>4）基于业务能力（类似用户服务，商品服务等等）</p>
<p>5）独立部署（迭代速度快）</p>
<p>6）无集中式管理（无须统一技术栈，可以根据不同的服务或者团队进行灵活选择）</p>
<p>ps：微服务的先行者Netflix公司，开源了一些好的微服务框架，后续会有介绍。</p>
<h1 id="2-怎么权衡微服务的利于弊"><a href="#2-怎么权衡微服务的利于弊" class="headerlink" title="2. 怎么权衡微服务的利于弊"></a>2. 怎么权衡微服务的利于弊</h1><p><strong>利：</strong></p>
<p>强模块边界 。（模块化的演化过程：类–&gt;组件/类库（sdk）–&gt;服务(service)，方式越来越灵活）</p>
<p>可独立部署。</p>
<p>技术多样性。</p>
<p><strong>弊：</strong></p>
<p>分布式复杂性。</p>
<p>最终一致性。（各个服务的团队，数据也是分散式治理，会出现不一致的问题）</p>
<p>运维复杂性。</p>
<p>测试复杂性。</p>
<h1 id="3-企业在什么时候考虑引入微服务"><a href="#3-企业在什么时候考虑引入微服务" class="headerlink" title="3. 企业在什么时候考虑引入微服务"></a>3. 企业在什么时候考虑引入微服务</h1><p>从生产力和系统的复杂性这两个方面来看。公司一开始的时候，业务复杂性不高，这时候是验证商业模式的时候，业务简单，用单体服务反而生产力很高。随着公司的发展，业务复杂性慢慢提高，这时候就可以采用微服务来提升生产力了。至于这个转化的点，需要团队的架构师来进行各方面衡量，就个人经验而言，团队发展到百人以上，采用微服务就很有必要了。</p>
<p>有些架构师是具有微服务架构能力，所以设计系统时就直接设计成了微服务，而不是通过单服务慢慢演化发展成微服务。在这里我并不推荐这种做法，因为一开始对业务领域并不是很了解，并且业务模式还没有得到验证，这时候上微服务风险比较高，很有可能失败。所以建议大家在单服务的应用成熟时，并且对业务领域比较熟悉的时候，如果发现单服务无法适应业务发展时，再考虑微服务的设计和架构。</p>
<h1 id="4-微服务的组织架构"><a href="#4-微服务的组织架构" class="headerlink" title="4.微服务的组织架构"></a>4.微服务的组织架构</h1><p><img src="https://upload-images.jianshu.io/upload_images/9727275-fa5840cb2dffd73c.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>如上图左边，传统的企业中，团队是按职能划分的。开发一个项目时，会从不同的职能团队找人进行开发，开发完成后，再各自回到自己的职能团队，这种模式实践证明，效率还是比较低的。</p>
<p>如上图右边，围绕每个业务线或产品，按服务划分团队。团队成员从架构到运维，形成一个完整的闭环。一直围绕在产品周围，进行不断的迭代。不会像传统的团队一样离开。这样开发效率会比较高。至于这种团队的规模，建议按照亚马逊的两个披萨原则，大概10人左右比较好。</p>
<h1 id="5：怎么理解中台战略和微服务"><a href="#5：怎么理解中台战略和微服务" class="headerlink" title="5：怎么理解中台战略和微服务"></a>5：怎么理解中台战略和微服务</h1><p>中台战略的由来：马云2015年去欧洲的一家公司supersell参观，发现这个公司的创新能力非常强，团队的规模很小，但是开发效率很高。他们就是采用中台战略。马云感触很深，回国后就在集团内部推出了中台战略。</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-3bc23e949167be80.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>简单的理解就是把传统的前后台体系中的后台进行了细分。阿里巴巴提出了大中台小前台的战略。就是强化业务和技术中台，把前端的应用变得更小更灵活。当中台越强大，能力就越强，越能更好的快速响应前台的业务需求。打个比喻，就是土壤越肥沃，越适合生长不同的生物，打造好的生态系统。</p>
<h1 id="6：服务分层"><a href="#6：服务分层" class="headerlink" title="6：服务分层"></a>6：服务分层</h1><p>每个公司的服务分层都不相同，有的公司服务没有分层，有的怎分层很多。目前业界没有统一的标准。</p>
<p>下面推荐一个比较容易理解的两层结构。</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-b8a1833e7fbccee1.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>1：基础服务： 比如一个电商网站，商品服务和订单服务就属于基础服务（核心领域服务）。缓存服务，监控服务，消息队列等也属于基础服务（公共服务）</p>
<p>2：聚合服务 ：例如网关服务就算一种聚合服务（适配服务）。</p>
<p>这是一种逻辑划分，不是物理划分，实际设计的东西很多很复杂。</p>
<h1 id="7：微服务的技术架构体系"><a href="#7：微服务的技术架构体系" class="headerlink" title="7：微服务的技术架构体系"></a>7：微服务的技术架构体系</h1><p>下图是一个成型的互联网微服务的架构体系：</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-2171043c8b5c1275.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>1：接入层 负载均衡作用，运维团队负责</p>
<p>2：网关层 反向路由，安全验证，限流等</p>
<p>3：业务服务层 基础服务和领域服务</p>
<p>4：支撑服务层</p>
<p>5：平台服务</p>
<p>6：基础设施层 运维团队负责。（或者阿里云）</p>
<h1 id="8：微服务的服务发现的三种方式"><a href="#8：微服务的服务发现的三种方式" class="headerlink" title="8：微服务的服务发现的三种方式"></a>8：微服务的服务发现的三种方式</h1><p>第一种：如下图所示，传统的服务发现（大部分公司的做法）。服务上线后，通知运维，申请域名，配置路由。调用方通过dns域名解析，经过负载均衡路由，进行服务访问。缺点： LB的单点风险，服务穿透LB，性能也不是太好</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-cbc517a4138ce04b.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>第二种：也叫客户端发现方式。如下图所示。通过服务注册的方式，服务提供者先注册服务。消费者通过注册中心获取相应服务。</p>
<p>并且把LB的功能移动到了消费者的进程内，消费者根据自身路由去获取相应服务。优点是，没有了LB单点问题，也没有了LB的中间一跳，性能也比较好。但是这种方式有一个非常明显的缺点就是具有非常强的耦合性。针对不同的语言，每个服务的客户端都得实现一套服务发现的功能。</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-ab57d008467aa8d5.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>第三种：也叫服务端发现方式，如下图所示。和第二种很相似。但是LB功能独立进程单独部署，所以解决了客户端多语言开发的问题。唯一的缺点就是运维成比较高，每个节点都得部署一个LB的代理，例如nginx。</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-008799d0bf8567ea.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<h1 id="9-微服务网关"><a href="#9-微服务网关" class="headerlink" title="9.微服务网关"></a>9.微服务网关</h1><p>网关就好比一个公司的门卫。屏蔽内部细节，统一对外服务接口。</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-0c0e7f1a63a5ab46.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>下图是一个网关所处位置的示例图。</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-ab3e08ec3c96c552.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<h1 id="10：Netflix-Zuul网关介绍"><a href="#10：Netflix-Zuul网关介绍" class="headerlink" title="10：Netflix Zuul网关介绍"></a>10：Netflix Zuul网关介绍</h1><p><img src="https://upload-images.jianshu.io/upload_images/9727275-aed7dd4159c6b218.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>核心就是一个servlet，通过filter机制实现的。主要分为三类过滤器：前置过滤器，过滤器和后置过滤器。</p>
<p>主要特色是，这些过滤器可以动态插拔，就是如果需要增加减少过滤器，可以不用重启，直接生效。原理就是：通过一个db维护过滤器（上图蓝色部分），如果增加过滤器，就将新过滤器编译完成后push到db中，有线程会定期扫描db，发现新的过滤器后，会上传到网关的相应文件目录下，并通知过滤器loader进行加载相应的过滤器。</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-38c33d3020495bd3.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>整个网关调用的流程</p>
<p>上图从左变http Request开始经过三类过滤器，最终到最右边的Http Response，这就是Zull网关的整个调用流程。</p>
<h1 id="11：微服务的路由发现体系"><a href="#11：微服务的路由发现体系" class="headerlink" title="11：微服务的路由发现体系"></a>11：微服务的路由发现体系</h1><p>整个微服务的路由发现体系，一般由服务注册中心和网关两部分组成。以NetFlix为例子，Eureka和Zull这两个组件支撑了netFlix整个的路由发现体系。如下图所示，首先外部请求发送到网关，网关去服务注册中心获取相应的服务，进行调用。其次内部服务间的调用，也通过服务注册中心进行的</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-c6d10feccef8194f.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<h1 id="12-微服务配置中心"><a href="#12-微服务配置中心" class="headerlink" title="12.微服务配置中心"></a>12.微服务配置中心</h1><p>目前大部分公司都是把配置写到配置文件中，遇到修改配置的情况，成本很高。并且没有修改配置的记录，出问题很难追溯。配置中心就接解决了以上的问题。</p>
<p>可配置内容：数据库连接，业务参数等等</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-e9a375181af20086.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>配置中心就是一个web服务，配置人员通过后台页面修改配置，各个服务就会得到新的配置参数。实现方式主要有两种，一种是push，另一种是pull。两张方式各有优缺点。push实时性较好，但是遇到网络抖动，会丢失消息。pull不会丢失消息但是实时性差一些。大家可以同时两种方式使用，实现一个比较好的效果。如下图所示，这是一个国内知名互联网公司的配置中心架构图。</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-28f047b7148f9f44.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>开源地址：<a href="http://github.com/ctripcorp/appollo" target="_blank" rel="noopener">http://github.com/ctripcorp/appollo</a></p>
<h1 id="13：RPC遇到了REST"><a href="#13：RPC遇到了REST" class="headerlink" title="13：RPC遇到了REST"></a>13：RPC遇到了REST</h1><p><img src="https://upload-images.jianshu.io/upload_images/9727275-1cf06ff95f4062a3.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>内部一些核心服务，性能要求比较高的可以采用RPC，对外服务的一般可以采用rest。</p>
<h1 id="14：服务框架和治理"><a href="#14：服务框架和治理" class="headerlink" title="14：服务框架和治理"></a>14：服务框架和治理</h1><p>微服务很多的时候，就需要有治理了。一个好的微服务框架一般分为以下14个部分。如下图所示。这就是开篇所说的，微服务涉及的东西很多，有些初创公司和业务不成熟的产品是不太适合的，成本比较高。</p>
<p>目前国内比较好的微服务框架就是阿里巴巴的DUBBO了,国外的就是spring cloud,大家可以去研究一下.</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-cf396ecab78e8092.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<h1 id="15：监控体系"><a href="#15：监控体系" class="headerlink" title="15：监控体系"></a>15：监控体系</h1><p>监控是微服务治理的重要环节。一般分为以下四层。如下图所示。</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-a6f01e73a16226d9.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>监控的内容分为五个部分：日志监控，Metrics监控（服务调用情况），调用链监控，告警系统和健康检查。</p>
<p>日志监控，国内常用的就是ELK+KAFKA来实现。健康检查和Metrics，像spring boot会自带。Nagios也是一个很好的开源监控框架。</p>
<h1 id="16-Trace调用链监控"><a href="#16-Trace调用链监控" class="headerlink" title="16:Trace调用链监控"></a>16:Trace调用链监控</h1><p>调用链监控是用来追踪微服务之前依赖的路径和问题定位。例如阿里的鹰眼系统。主要原理就是子节点会记录父节点的id信息。</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-04079de2314615bf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>下图是目前比较流行的调用链监控框架。</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-bb18193d08fc64a0.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<h1 id="17：微服务的限流熔断"><a href="#17：微服务的限流熔断" class="headerlink" title="17：微服务的限流熔断"></a>17：微服务的限流熔断</h1><p>假设服务A依赖服务B和服务C，而B服务和C服务有可能继续依赖其他的服务，继续下去会使得调用链路过长。如果在A的链路上某个或几个被调用的子服务不可用或延迟较高，则会导致调用A服务的请求被堵住，堵住的请求会消耗占用掉系统的线程、io等资源，当该类请求越来越多，占用的计算机资源越来越多的时候，会导致系统瓶颈出现，造成其他的请求同样不可用，最终导致业务系统崩溃。</p>
<p>一般情况对于服务依赖的保护主要有两种方式：熔断和限流。目前最流行的就是Hystrix的熔断框架。</p>
<p>下图是Hystrix的断路器原理图：</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-04f848618c7146af.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>限流方式可以采用zuul的API限流方法。</p>
<h1 id="18-Docker-容器部署技术-amp-持续交付流水线"><a href="#18-Docker-容器部署技术-amp-持续交付流水线" class="headerlink" title="18.Docker 容器部署技术&amp;持续交付流水线"></a>18.Docker 容器部署技术&amp;持续交付流水线</h1><p>随着微服务的流行，容器技术也相应的被大家重视起来。容器技术主要解决了以下两个问题：</p>
<p>1：环境一致性问题。例如java的jar/war包部署会依赖于环境的问题（操着系统的版本，jdk版本问题）。</p>
<p>2：镜像部署问题。例如java，rubby，nodejs等等的发布系统是不一样的，每个环境都得很麻烦的部署一遍，采用docker镜像，就屏蔽了这类问题。</p>
<p>下图是Docker容器部署的一个完整过程。</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-55bdf456e13b3e99.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>更重要的是，拥有如此多服务的集群环境迁移、复制也非常轻松，只需选择好各服务对应的Docker服务镜像、配置好相互之间访问地址就能很快搭建出一份完全一样的新集群。</p>
<h1 id="19-容器调度和发布体系"><a href="#19-容器调度和发布体系" class="headerlink" title="19.容器调度和发布体系"></a>19.容器调度和发布体系</h1><p>目前基于容器的调度平台有Kubernetes，mesos，omega。下图是mesos的一个简单架构示意图。</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-6ebc922a92112496.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>
<p>下图是一个完整的容器发布体系</p>
<p><img src="https://upload-images.jianshu.io/upload_images/9727275-4855f3a88e0fafd7.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640" alt="img"></p>

      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/blog/2020/01/11/%E4%BB%80%E4%B9%88%E6%98%AF%E5%BE%AE%E6%9C%8D%E5%8A%A1/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-07-Redis系列之-Redis-Sentinel" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2019/12/31/07-Redis%E7%B3%BB%E5%88%97%E4%B9%8B-Redis-Sentinel/">07-Redis系列之-Redis-Sentinel</a>
    </h1>
  

        
        <a href="/blog/2019/12/31/07-Redis%E7%B3%BB%E5%88%97%E4%B9%8B-Redis-Sentinel/" class="archive-article-date">
  	<time datetime="2019-12-31T11:43:54.838Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2019-12-31</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="一-主从复制高可用"><a href="#一-主从复制高可用" class="headerlink" title="一 主从复制高可用"></a>一 主从复制高可用</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#主从复制存在的问题：</span></span><br><span class="line"><span class="comment">#1 主从复制，主节点发生故障，需要做故障转移，可以手动转移：让其中一个slave变成master</span></span><br><span class="line"><span class="comment">#2 主从复制，只能主写数据，所以写能力和存储能力有限</span></span><br></pre></td></tr></table></figure>

<h2 id="二-架构说明"><a href="#二-架构说明" class="headerlink" title="二 架构说明"></a>二 架构说明</h2><p>可以做故障判断，故障转移，通知客户端（其实是一个进程），客户端直接连接sentinel的地址</p>
<img src="https://tva1.sinaimg.cn/large/006tNbRwgy1gadzuhodicj30oe0dc0y9.jpg" alt="image-20191229230823911" style="zoom:50%;" />

<p>1 多个sentinel发现并确认master有问题</p>
<p>2 选举触一个sentinel作为领导</p>
<p>3 选取一个slave作为新的master</p>
<p>4 通知其余slave成为新的master的slave</p>
<p>5 通知客户端主从变化</p>
<p>6 等待老的master复活成为新master的slave</p>
<h2 id="三-安装配置"><a href="#三-安装配置" class="headerlink" title="三 安装配置"></a>三 安装配置</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span> 配置开启主从节点</span><br><span class="line"><span class="number">2</span> 配置开启sentinel监控主节点（sentinel是特殊的redis）</span><br><span class="line"><span class="number">3</span> 应该是多台机器</span><br></pre></td></tr></table></figure>

<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#配置开启sentinel监控主节点</span></span><br><span class="line">mkdir -p redis4/conf redis4/data redis5/conf redis5/data redis6/data redis6/conf</span><br><span class="line"></span><br><span class="line">vi sentinel.conf</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">port <span class="number">26379</span></span><br><span class="line">daemonize no</span><br><span class="line">dir /data</span><br><span class="line">protected-mode no</span><br><span class="line">bind <span class="number">0.0</span><span class="number">.0</span><span class="number">.0</span></span><br><span class="line">logfile <span class="string">"redis_sentinel.log"</span></span><br><span class="line">sentinel monitor mymaster <span class="number">10.0</span><span class="number">.0</span><span class="number">.1</span> <span class="number">6379</span> <span class="number">2</span></span><br><span class="line">sentinel down-after-milliseconds mymaster <span class="number">30000</span></span><br><span class="line">sentinel parallel-syncs mymaster <span class="number">1</span></span><br><span class="line">sentinel failover-timeout mymaster <span class="number">180000</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">docker run -p <span class="number">26379</span>:<span class="number">26379</span> --name redis_26379 -v /home/redis4/conf/sentinel.conf:/etc/redis/sentinel.conf -v /home/redis4/data:/data -d redis redis-sentinel /etc/redis/sentinel.conf</span><br><span class="line"></span><br><span class="line">docker run -p <span class="number">26378</span>:<span class="number">26379</span> --name redis_26378 -v /home/redis5/conf/sentinel.conf:/etc/redis/sentinel.conf -v /home/redis5/data:/data -d redis redis-sentinel /etc/redis/sentinel.conf</span><br><span class="line"></span><br><span class="line">docker run -p <span class="number">26377</span>:<span class="number">26379</span> --name redis_26377 -v /home/redis6/conf/sentinel.conf:/etc/redis/sentinel.conf -v /home/redis6/data:/data -d redis redis-sentinel /etc/redis/sentinel.conf</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">redis-sentinel sentinel.conf</span><br><span class="line"></span><br><span class="line">info</span><br><span class="line">配置会重写，自动发现slave</span><br></pre></td></tr></table></figure>



<h2 id="四-客户端连接"><a href="#四-客户端连接" class="headerlink" title="四 客户端连接"></a>四 客户端连接</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> redis</span><br><span class="line"><span class="keyword">from</span> redis.sentinel <span class="keyword">import</span> Sentinel</span><br><span class="line"></span><br><span class="line"><span class="comment"># 连接哨兵服务器(主机名也可以用域名)</span></span><br><span class="line"><span class="comment"># 10.0.0.101:26379</span></span><br><span class="line">sentinel = Sentinel([(<span class="string">'10.0.0.101'</span>, <span class="number">26379</span>),</span><br><span class="line">                     (<span class="string">'10.0.0.101'</span>, <span class="number">26378</span>),</span><br><span class="line">                     (<span class="string">'10.0.0.101'</span>, <span class="number">26377</span>)</span><br><span class="line">		     ],</span><br><span class="line">                    socket_timeout=<span class="number">5</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">print(sentinel)</span><br><span class="line"><span class="comment"># 获取主服务器地址</span></span><br><span class="line">master = sentinel.discover_master(<span class="string">'mymaster'</span>)</span><br><span class="line">print(master)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取从服务器地址</span></span><br><span class="line">slave = sentinel.discover_slaves(<span class="string">'mymaster'</span>)</span><br><span class="line">print(slave)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取主服务器进行写入</span></span><br><span class="line"><span class="comment"># master = sentinel.master_for('mymaster', socket_timeout=0.5)</span></span><br><span class="line"><span class="comment"># w_ret = master.set('foo', 'bar')</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># slave = sentinel.slave_for('mymaster', socket_timeout=0.5)</span></span><br><span class="line"><span class="comment"># r_ret = slave.get('foo')</span></span><br><span class="line"><span class="comment"># print(r_ret)</span></span><br></pre></td></tr></table></figure>



<h2 id="五-实现原理"><a href="#五-实现原理" class="headerlink" title="五 实现原理"></a>五 实现原理</h2><h2 id="六-常见问题"><a href="#六-常见问题" class="headerlink" title="六 常见问题"></a>六 常见问题</h2>
      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/blog/2019/12/31/07-Redis%E7%B3%BB%E5%88%97%E4%B9%8B-Redis-Sentinel/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
  
    <nav id="page-nav">
      <span class="page-number current">1</span><a class="page-number" href="/blog/page/2/">2</a><a class="page-number" href="/blog/page/3/">3</a><a class="page-number" href="/blog/page/4/">4</a><a class="extend next" rel="next" href="/blog/page/2/">Next &amp;raquo;</a>
    </nav>
  


          </div>
        </div>
      </div>
      <footer id="footer">
  <div class="outer">
    <div id="footer-info">
    	<div class="footer-left">
    		&copy; 2020 CozyMo
    	</div>
      	<div class="footer-right">
      		<a href="http://hexo.io/" target="_blank">Hexo</a>  Theme <a href="https://github.com/litten/hexo-theme-yilia" target="_blank">Yilia</a> by Litten
      	</div>
    </div>
  </div>
</footer>
    </div>
    <script>
	var yiliaConfig = {
		mathjax: false,
		isHome: true,
		isPost: false,
		isArchive: false,
		isTag: false,
		isCategory: false,
		open_in_new: false,
		toc_hide_index: true,
		root: "/blog/",
		innerArchive: true,
		showTags: false
	}
</script>

<script>!function(t){function n(e){if(r[e])return r[e].exports;var i=r[e]={exports:{},id:e,loaded:!1};return t[e].call(i.exports,i,i.exports,n),i.loaded=!0,i.exports}var r={};n.m=t,n.c=r,n.p="./",n(0)}([function(t,n,r){r(195),t.exports=r(191)},function(t,n,r){var e=r(3),i=r(52),o=r(27),u=r(28),c=r(53),f="prototype",a=function(t,n,r){var s,l,h,v,p=t&a.F,d=t&a.G,y=t&a.S,g=t&a.P,b=t&a.B,m=d?e:y?e[n]||(e[n]={}):(e[n]||{})[f],x=d?i:i[n]||(i[n]={}),w=x[f]||(x[f]={});d&&(r=n);for(s in r)l=!p&&m&&void 0!==m[s],h=(l?m:r)[s],v=b&&l?c(h,e):g&&"function"==typeof h?c(Function.call,h):h,m&&u(m,s,h,t&a.U),x[s]!=h&&o(x,s,v),g&&w[s]!=h&&(w[s]=h)};e.core=i,a.F=1,a.G=2,a.S=4,a.P=8,a.B=16,a.W=32,a.U=64,a.R=128,t.exports=a},function(t,n,r){var e=r(6);t.exports=function(t){if(!e(t))throw TypeError(t+" is not an object!");return t}},function(t,n){var r=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=r)},function(t,n){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,n){var r=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=r)},function(t,n){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,n,r){var e=r(126)("wks"),i=r(76),o=r(3).Symbol,u="function"==typeof o;(t.exports=function(t){return e[t]||(e[t]=u&&o[t]||(u?o:i)("Symbol."+t))}).store=e},function(t,n){var r={}.hasOwnProperty;t.exports=function(t,n){return r.call(t,n)}},function(t,n,r){var e=r(94),i=r(33);t.exports=function(t){return e(i(t))}},function(t,n,r){t.exports=!r(4)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(t,n,r){var e=r(2),i=r(167),o=r(50),u=Object.defineProperty;n.f=r(10)?Object.defineProperty:function(t,n,r){if(e(t),n=o(n,!0),e(r),i)try{return u(t,n,r)}catch(t){}if("get"in r||"set"in r)throw TypeError("Accessors not supported!");return"value"in r&&(t[n]=r.value),t}},function(t,n,r){t.exports=!r(18)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(t,n,r){var e=r(14),i=r(22);t.exports=r(12)?function(t,n,r){return e.f(t,n,i(1,r))}:function(t,n,r){return t[n]=r,t}},function(t,n,r){var e=r(20),i=r(58),o=r(42),u=Object.defineProperty;n.f=r(12)?Object.defineProperty:function(t,n,r){if(e(t),n=o(n,!0),e(r),i)try{return u(t,n,r)}catch(t){}if("get"in r||"set"in r)throw TypeError("Accessors not supported!");return"value"in r&&(t[n]=r.value),t}},function(t,n,r){var e=r(40)("wks"),i=r(23),o=r(5).Symbol,u="function"==typeof o;(t.exports=function(t){return e[t]||(e[t]=u&&o[t]||(u?o:i)("Symbol."+t))}).store=e},function(t,n,r){var e=r(67),i=Math.min;t.exports=function(t){return t>0?i(e(t),9007199254740991):0}},function(t,n,r){var e=r(46);t.exports=function(t){return Object(e(t))}},function(t,n){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,n,r){var e=r(63),i=r(34);t.exports=Object.keys||function(t){return e(t,i)}},function(t,n,r){var e=r(21);t.exports=function(t){if(!e(t))throw TypeError(t+" is not an object!");return t}},function(t,n){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,n){t.exports=function(t,n){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:n}}},function(t,n){var r=0,e=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++r+e).toString(36))}},function(t,n){var r={}.hasOwnProperty;t.exports=function(t,n){return r.call(t,n)}},function(t,n){var r=t.exports={version:"2.4.0"};"number"==typeof __e&&(__e=r)},function(t,n){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},function(t,n,r){var e=r(11),i=r(66);t.exports=r(10)?function(t,n,r){return e.f(t,n,i(1,r))}:function(t,n,r){return t[n]=r,t}},function(t,n,r){var e=r(3),i=r(27),o=r(24),u=r(76)("src"),c="toString",f=Function[c],a=(""+f).split(c);r(52).inspectSource=function(t){return f.call(t)},(t.exports=function(t,n,r,c){var f="function"==typeof r;f&&(o(r,"name")||i(r,"name",n)),t[n]!==r&&(f&&(o(r,u)||i(r,u,t[n]?""+t[n]:a.join(String(n)))),t===e?t[n]=r:c?t[n]?t[n]=r:i(t,n,r):(delete t[n],i(t,n,r)))})(Function.prototype,c,function(){return"function"==typeof this&&this[u]||f.call(this)})},function(t,n,r){var e=r(1),i=r(4),o=r(46),u=function(t,n,r,e){var i=String(o(t)),u="<"+n;return""!==r&&(u+=" "+r+'="'+String(e).replace(/"/g,"&quot;")+'"'),u+">"+i+"</"+n+">"};t.exports=function(t,n){var r={};r[t]=n(u),e(e.P+e.F*i(function(){var n=""[t]('"');return n!==n.toLowerCase()||n.split('"').length>3}),"String",r)}},function(t,n,r){var e=r(115),i=r(46);t.exports=function(t){return e(i(t))}},function(t,n,r){var e=r(116),i=r(66),o=r(30),u=r(50),c=r(24),f=r(167),a=Object.getOwnPropertyDescriptor;n.f=r(10)?a:function(t,n){if(t=o(t),n=u(n,!0),f)try{return a(t,n)}catch(t){}if(c(t,n))return i(!e.f.call(t,n),t[n])}},function(t,n,r){var e=r(24),i=r(17),o=r(145)("IE_PROTO"),u=Object.prototype;t.exports=Object.getPrototypeOf||function(t){return t=i(t),e(t,o)?t[o]:"function"==typeof t.constructor&&t instanceof t.constructor?t.constructor.prototype:t instanceof Object?u:null}},function(t,n){t.exports=function(t){if(void 0==t)throw TypeError("Can't call method on  "+t);return t}},function(t,n){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(t,n){t.exports={}},function(t,n){t.exports=!0},function(t,n){n.f={}.propertyIsEnumerable},function(t,n,r){var e=r(14).f,i=r(8),o=r(15)("toStringTag");t.exports=function(t,n,r){t&&!i(t=r?t:t.prototype,o)&&e(t,o,{configurable:!0,value:n})}},function(t,n,r){var e=r(40)("keys"),i=r(23);t.exports=function(t){return e[t]||(e[t]=i(t))}},function(t,n,r){var e=r(5),i="__core-js_shared__",o=e[i]||(e[i]={});t.exports=function(t){return o[t]||(o[t]={})}},function(t,n){var r=Math.ceil,e=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?e:r)(t)}},function(t,n,r){var e=r(21);t.exports=function(t,n){if(!e(t))return t;var r,i;if(n&&"function"==typeof(r=t.toString)&&!e(i=r.call(t)))return i;if("function"==typeof(r=t.valueOf)&&!e(i=r.call(t)))return i;if(!n&&"function"==typeof(r=t.toString)&&!e(i=r.call(t)))return i;throw TypeError("Can't convert object to primitive value")}},function(t,n,r){var e=r(5),i=r(25),o=r(36),u=r(44),c=r(14).f;t.exports=function(t){var n=i.Symbol||(i.Symbol=o?{}:e.Symbol||{});"_"==t.charAt(0)||t in n||c(n,t,{value:u.f(t)})}},function(t,n,r){n.f=r(15)},function(t,n){var r={}.toString;t.exports=function(t){return r.call(t).slice(8,-1)}},function(t,n){t.exports=function(t){if(void 0==t)throw TypeError("Can't call method on  "+t);return t}},function(t,n,r){var e=r(4);t.exports=function(t,n){return!!t&&e(function(){n?t.call(null,function(){},1):t.call(null)})}},function(t,n,r){var e=r(53),i=r(115),o=r(17),u=r(16),c=r(203);t.exports=function(t,n){var r=1==t,f=2==t,a=3==t,s=4==t,l=6==t,h=5==t||l,v=n||c;return function(n,c,p){for(var d,y,g=o(n),b=i(g),m=e(c,p,3),x=u(b.length),w=0,S=r?v(n,x):f?v(n,0):void 0;x>w;w++)if((h||w in b)&&(d=b[w],y=m(d,w,g),t))if(r)S[w]=y;else if(y)switch(t){case 3:return!0;case 5:return d;case 6:return w;case 2:S.push(d)}else if(s)return!1;return l?-1:a||s?s:S}}},function(t,n,r){var e=r(1),i=r(52),o=r(4);t.exports=function(t,n){var r=(i.Object||{})[t]||Object[t],u={};u[t]=n(r),e(e.S+e.F*o(function(){r(1)}),"Object",u)}},function(t,n,r){var e=r(6);t.exports=function(t,n){if(!e(t))return t;var r,i;if(n&&"function"==typeof(r=t.toString)&&!e(i=r.call(t)))return i;if("function"==typeof(r=t.valueOf)&&!e(i=r.call(t)))return i;if(!n&&"function"==typeof(r=t.toString)&&!e(i=r.call(t)))return i;throw TypeError("Can't convert object to primitive value")}},function(t,n,r){var e=r(5),i=r(25),o=r(91),u=r(13),c="prototype",f=function(t,n,r){var a,s,l,h=t&f.F,v=t&f.G,p=t&f.S,d=t&f.P,y=t&f.B,g=t&f.W,b=v?i:i[n]||(i[n]={}),m=b[c],x=v?e:p?e[n]:(e[n]||{})[c];v&&(r=n);for(a in r)(s=!h&&x&&void 0!==x[a])&&a in b||(l=s?x[a]:r[a],b[a]=v&&"function"!=typeof x[a]?r[a]:y&&s?o(l,e):g&&x[a]==l?function(t){var n=function(n,r,e){if(this instanceof t){switch(arguments.length){case 0:return new t;case 1:return new t(n);case 2:return new t(n,r)}return new t(n,r,e)}return t.apply(this,arguments)};return n[c]=t[c],n}(l):d&&"function"==typeof l?o(Function.call,l):l,d&&((b.virtual||(b.virtual={}))[a]=l,t&f.R&&m&&!m[a]&&u(m,a,l)))};f.F=1,f.G=2,f.S=4,f.P=8,f.B=16,f.W=32,f.U=64,f.R=128,t.exports=f},function(t,n){var r=t.exports={version:"2.4.0"};"number"==typeof __e&&(__e=r)},function(t,n,r){var e=r(26);t.exports=function(t,n,r){if(e(t),void 0===n)return t;switch(r){case 1:return function(r){return t.call(n,r)};case 2:return function(r,e){return t.call(n,r,e)};case 3:return function(r,e,i){return t.call(n,r,e,i)}}return function(){return t.apply(n,arguments)}}},function(t,n,r){var e=r(183),i=r(1),o=r(126)("metadata"),u=o.store||(o.store=new(r(186))),c=function(t,n,r){var i=u.get(t);if(!i){if(!r)return;u.set(t,i=new e)}var o=i.get(n);if(!o){if(!r)return;i.set(n,o=new e)}return o},f=function(t,n,r){var e=c(n,r,!1);return void 0!==e&&e.has(t)},a=function(t,n,r){var e=c(n,r,!1);return void 0===e?void 0:e.get(t)},s=function(t,n,r,e){c(r,e,!0).set(t,n)},l=function(t,n){var r=c(t,n,!1),e=[];return r&&r.forEach(function(t,n){e.push(n)}),e},h=function(t){return void 0===t||"symbol"==typeof t?t:String(t)},v=function(t){i(i.S,"Reflect",t)};t.exports={store:u,map:c,has:f,get:a,set:s,keys:l,key:h,exp:v}},function(t,n,r){"use strict";if(r(10)){var e=r(69),i=r(3),o=r(4),u=r(1),c=r(127),f=r(152),a=r(53),s=r(68),l=r(66),h=r(27),v=r(73),p=r(67),d=r(16),y=r(75),g=r(50),b=r(24),m=r(180),x=r(114),w=r(6),S=r(17),_=r(137),O=r(70),E=r(32),P=r(71).f,j=r(154),F=r(76),M=r(7),A=r(48),N=r(117),T=r(146),I=r(155),k=r(80),L=r(123),R=r(74),C=r(130),D=r(160),U=r(11),W=r(31),G=U.f,B=W.f,V=i.RangeError,z=i.TypeError,q=i.Uint8Array,K="ArrayBuffer",J="Shared"+K,Y="BYTES_PER_ELEMENT",H="prototype",$=Array[H],X=f.ArrayBuffer,Q=f.DataView,Z=A(0),tt=A(2),nt=A(3),rt=A(4),et=A(5),it=A(6),ot=N(!0),ut=N(!1),ct=I.values,ft=I.keys,at=I.entries,st=$.lastIndexOf,lt=$.reduce,ht=$.reduceRight,vt=$.join,pt=$.sort,dt=$.slice,yt=$.toString,gt=$.toLocaleString,bt=M("iterator"),mt=M("toStringTag"),xt=F("typed_constructor"),wt=F("def_constructor"),St=c.CONSTR,_t=c.TYPED,Ot=c.VIEW,Et="Wrong length!",Pt=A(1,function(t,n){return Tt(T(t,t[wt]),n)}),jt=o(function(){return 1===new q(new Uint16Array([1]).buffer)[0]}),Ft=!!q&&!!q[H].set&&o(function(){new q(1).set({})}),Mt=function(t,n){if(void 0===t)throw z(Et);var r=+t,e=d(t);if(n&&!m(r,e))throw V(Et);return e},At=function(t,n){var r=p(t);if(r<0||r%n)throw V("Wrong offset!");return r},Nt=function(t){if(w(t)&&_t in t)return t;throw z(t+" is not a typed array!")},Tt=function(t,n){if(!(w(t)&&xt in t))throw z("It is not a typed array constructor!");return new t(n)},It=function(t,n){return kt(T(t,t[wt]),n)},kt=function(t,n){for(var r=0,e=n.length,i=Tt(t,e);e>r;)i[r]=n[r++];return i},Lt=function(t,n,r){G(t,n,{get:function(){return this._d[r]}})},Rt=function(t){var n,r,e,i,o,u,c=S(t),f=arguments.length,s=f>1?arguments[1]:void 0,l=void 0!==s,h=j(c);if(void 0!=h&&!_(h)){for(u=h.call(c),e=[],n=0;!(o=u.next()).done;n++)e.push(o.value);c=e}for(l&&f>2&&(s=a(s,arguments[2],2)),n=0,r=d(c.length),i=Tt(this,r);r>n;n++)i[n]=l?s(c[n],n):c[n];return i},Ct=function(){for(var t=0,n=arguments.length,r=Tt(this,n);n>t;)r[t]=arguments[t++];return r},Dt=!!q&&o(function(){gt.call(new q(1))}),Ut=function(){return gt.apply(Dt?dt.call(Nt(this)):Nt(this),arguments)},Wt={copyWithin:function(t,n){return D.call(Nt(this),t,n,arguments.length>2?arguments[2]:void 0)},every:function(t){return rt(Nt(this),t,arguments.length>1?arguments[1]:void 0)},fill:function(t){return C.apply(Nt(this),arguments)},filter:function(t){return It(this,tt(Nt(this),t,arguments.length>1?arguments[1]:void 0))},find:function(t){return et(Nt(this),t,arguments.length>1?arguments[1]:void 0)},findIndex:function(t){return it(Nt(this),t,arguments.length>1?arguments[1]:void 0)},forEach:function(t){Z(Nt(this),t,arguments.length>1?arguments[1]:void 0)},indexOf:function(t){return ut(Nt(this),t,arguments.length>1?arguments[1]:void 0)},includes:function(t){return ot(Nt(this),t,arguments.length>1?arguments[1]:void 0)},join:function(t){return vt.apply(Nt(this),arguments)},lastIndexOf:function(t){return st.apply(Nt(this),arguments)},map:function(t){return Pt(Nt(this),t,arguments.length>1?arguments[1]:void 0)},reduce:function(t){return lt.apply(Nt(this),arguments)},reduceRight:function(t){return ht.apply(Nt(this),arguments)},reverse:function(){for(var t,n=this,r=Nt(n).length,e=Math.floor(r/2),i=0;i<e;)t=n[i],n[i++]=n[--r],n[r]=t;return n},some:function(t){return nt(Nt(this),t,arguments.length>1?arguments[1]:void 0)},sort:function(t){return pt.call(Nt(this),t)},subarray:function(t,n){var r=Nt(this),e=r.length,i=y(t,e);return new(T(r,r[wt]))(r.buffer,r.byteOffset+i*r.BYTES_PER_ELEMENT,d((void 0===n?e:y(n,e))-i))}},Gt=function(t,n){return It(this,dt.call(Nt(this),t,n))},Bt=function(t){Nt(this);var n=At(arguments[1],1),r=this.length,e=S(t),i=d(e.length),o=0;if(i+n>r)throw V(Et);for(;o<i;)this[n+o]=e[o++]},Vt={entries:function(){return at.call(Nt(this))},keys:function(){return ft.call(Nt(this))},values:function(){return ct.call(Nt(this))}},zt=function(t,n){return w(t)&&t[_t]&&"symbol"!=typeof n&&n in t&&String(+n)==String(n)},qt=function(t,n){return zt(t,n=g(n,!0))?l(2,t[n]):B(t,n)},Kt=function(t,n,r){return!(zt(t,n=g(n,!0))&&w(r)&&b(r,"value"))||b(r,"get")||b(r,"set")||r.configurable||b(r,"writable")&&!r.writable||b(r,"enumerable")&&!r.enumerable?G(t,n,r):(t[n]=r.value,t)};St||(W.f=qt,U.f=Kt),u(u.S+u.F*!St,"Object",{getOwnPropertyDescriptor:qt,defineProperty:Kt}),o(function(){yt.call({})})&&(yt=gt=function(){return vt.call(this)});var Jt=v({},Wt);v(Jt,Vt),h(Jt,bt,Vt.values),v(Jt,{slice:Gt,set:Bt,constructor:function(){},toString:yt,toLocaleString:Ut}),Lt(Jt,"buffer","b"),Lt(Jt,"byteOffset","o"),Lt(Jt,"byteLength","l"),Lt(Jt,"length","e"),G(Jt,mt,{get:function(){return this[_t]}}),t.exports=function(t,n,r,f){f=!!f;var a=t+(f?"Clamped":"")+"Array",l="Uint8Array"!=a,v="get"+t,p="set"+t,y=i[a],g=y||{},b=y&&E(y),m=!y||!c.ABV,S={},_=y&&y[H],j=function(t,r){var e=t._d;return e.v[v](r*n+e.o,jt)},F=function(t,r,e){var i=t._d;f&&(e=(e=Math.round(e))<0?0:e>255?255:255&e),i.v[p](r*n+i.o,e,jt)},M=function(t,n){G(t,n,{get:function(){return j(this,n)},set:function(t){return F(this,n,t)},enumerable:!0})};m?(y=r(function(t,r,e,i){s(t,y,a,"_d");var o,u,c,f,l=0,v=0;if(w(r)){if(!(r instanceof X||(f=x(r))==K||f==J))return _t in r?kt(y,r):Rt.call(y,r);o=r,v=At(e,n);var p=r.byteLength;if(void 0===i){if(p%n)throw V(Et);if((u=p-v)<0)throw V(Et)}else if((u=d(i)*n)+v>p)throw V(Et);c=u/n}else c=Mt(r,!0),u=c*n,o=new X(u);for(h(t,"_d",{b:o,o:v,l:u,e:c,v:new Q(o)});l<c;)M(t,l++)}),_=y[H]=O(Jt),h(_,"constructor",y)):L(function(t){new y(null),new y(t)},!0)||(y=r(function(t,r,e,i){s(t,y,a);var o;return w(r)?r instanceof X||(o=x(r))==K||o==J?void 0!==i?new g(r,At(e,n),i):void 0!==e?new g(r,At(e,n)):new g(r):_t in r?kt(y,r):Rt.call(y,r):new g(Mt(r,l))}),Z(b!==Function.prototype?P(g).concat(P(b)):P(g),function(t){t in y||h(y,t,g[t])}),y[H]=_,e||(_.constructor=y));var A=_[bt],N=!!A&&("values"==A.name||void 0==A.name),T=Vt.values;h(y,xt,!0),h(_,_t,a),h(_,Ot,!0),h(_,wt,y),(f?new y(1)[mt]==a:mt in _)||G(_,mt,{get:function(){return a}}),S[a]=y,u(u.G+u.W+u.F*(y!=g),S),u(u.S,a,{BYTES_PER_ELEMENT:n,from:Rt,of:Ct}),Y in _||h(_,Y,n),u(u.P,a,Wt),R(a),u(u.P+u.F*Ft,a,{set:Bt}),u(u.P+u.F*!N,a,Vt),u(u.P+u.F*(_.toString!=yt),a,{toString:yt}),u(u.P+u.F*o(function(){new y(1).slice()}),a,{slice:Gt}),u(u.P+u.F*(o(function(){return[1,2].toLocaleString()!=new y([1,2]).toLocaleString()})||!o(function(){_.toLocaleString.call([1,2])})),a,{toLocaleString:Ut}),k[a]=N?A:T,e||N||h(_,bt,T)}}else t.exports=function(){}},function(t,n){var r={}.toString;t.exports=function(t){return r.call(t).slice(8,-1)}},function(t,n,r){var e=r(21),i=r(5).document,o=e(i)&&e(i.createElement);t.exports=function(t){return o?i.createElement(t):{}}},function(t,n,r){t.exports=!r(12)&&!r(18)(function(){return 7!=Object.defineProperty(r(57)("div"),"a",{get:function(){return 7}}).a})},function(t,n,r){"use strict";var e=r(36),i=r(51),o=r(64),u=r(13),c=r(8),f=r(35),a=r(96),s=r(38),l=r(103),h=r(15)("iterator"),v=!([].keys&&"next"in[].keys()),p="keys",d="values",y=function(){return this};t.exports=function(t,n,r,g,b,m,x){a(r,n,g);var w,S,_,O=function(t){if(!v&&t in F)return F[t];switch(t){case p:case d:return function(){return new r(this,t)}}return function(){return new r(this,t)}},E=n+" Iterator",P=b==d,j=!1,F=t.prototype,M=F[h]||F["@@iterator"]||b&&F[b],A=M||O(b),N=b?P?O("entries"):A:void 0,T="Array"==n?F.entries||M:M;if(T&&(_=l(T.call(new t)))!==Object.prototype&&(s(_,E,!0),e||c(_,h)||u(_,h,y)),P&&M&&M.name!==d&&(j=!0,A=function(){return M.call(this)}),e&&!x||!v&&!j&&F[h]||u(F,h,A),f[n]=A,f[E]=y,b)if(w={values:P?A:O(d),keys:m?A:O(p),entries:N},x)for(S in w)S in F||o(F,S,w[S]);else i(i.P+i.F*(v||j),n,w);return w}},function(t,n,r){var e=r(20),i=r(100),o=r(34),u=r(39)("IE_PROTO"),c=function(){},f="prototype",a=function(){var t,n=r(57)("iframe"),e=o.length;for(n.style.display="none",r(93).appendChild(n),n.src="javascript:",t=n.contentWindow.document,t.open(),t.write("<script>document.F=Object<\/script>"),t.close(),a=t.F;e--;)delete a[f][o[e]];return a()};t.exports=Object.create||function(t,n){var r;return null!==t?(c[f]=e(t),r=new c,c[f]=null,r[u]=t):r=a(),void 0===n?r:i(r,n)}},function(t,n,r){var e=r(63),i=r(34).concat("length","prototype");n.f=Object.getOwnPropertyNames||function(t){return e(t,i)}},function(t,n){n.f=Object.getOwnPropertySymbols},function(t,n,r){var e=r(8),i=r(9),o=r(90)(!1),u=r(39)("IE_PROTO");t.exports=function(t,n){var r,c=i(t),f=0,a=[];for(r in c)r!=u&&e(c,r)&&a.push(r);for(;n.length>f;)e(c,r=n[f++])&&(~o(a,r)||a.push(r));return a}},function(t,n,r){t.exports=r(13)},function(t,n,r){var e=r(76)("meta"),i=r(6),o=r(24),u=r(11).f,c=0,f=Object.isExtensible||function(){return!0},a=!r(4)(function(){return f(Object.preventExtensions({}))}),s=function(t){u(t,e,{value:{i:"O"+ ++c,w:{}}})},l=function(t,n){if(!i(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!o(t,e)){if(!f(t))return"F";if(!n)return"E";s(t)}return t[e].i},h=function(t,n){if(!o(t,e)){if(!f(t))return!0;if(!n)return!1;s(t)}return t[e].w},v=function(t){return a&&p.NEED&&f(t)&&!o(t,e)&&s(t),t},p=t.exports={KEY:e,NEED:!1,fastKey:l,getWeak:h,onFreeze:v}},function(t,n){t.exports=function(t,n){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:n}}},function(t,n){var r=Math.ceil,e=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?e:r)(t)}},function(t,n){t.exports=function(t,n,r,e){if(!(t instanceof n)||void 0!==e&&e in t)throw TypeError(r+": incorrect invocation!");return t}},function(t,n){t.exports=!1},function(t,n,r){var e=r(2),i=r(173),o=r(133),u=r(145)("IE_PROTO"),c=function(){},f="prototype",a=function(){var t,n=r(132)("iframe"),e=o.length;for(n.style.display="none",r(135).appendChild(n),n.src="javascript:",t=n.contentWindow.document,t.open(),t.write("<script>document.F=Object<\/script>"),t.close(),a=t.F;e--;)delete a[f][o[e]];return a()};t.exports=Object.create||function(t,n){var r;return null!==t?(c[f]=e(t),r=new c,c[f]=null,r[u]=t):r=a(),void 0===n?r:i(r,n)}},function(t,n,r){var e=r(175),i=r(133).concat("length","prototype");n.f=Object.getOwnPropertyNames||function(t){return e(t,i)}},function(t,n,r){var e=r(175),i=r(133);t.exports=Object.keys||function(t){return e(t,i)}},function(t,n,r){var e=r(28);t.exports=function(t,n,r){for(var i in n)e(t,i,n[i],r);return t}},function(t,n,r){"use strict";var e=r(3),i=r(11),o=r(10),u=r(7)("species");t.exports=function(t){var n=e[t];o&&n&&!n[u]&&i.f(n,u,{configurable:!0,get:function(){return this}})}},function(t,n,r){var e=r(67),i=Math.max,o=Math.min;t.exports=function(t,n){return t=e(t),t<0?i(t+n,0):o(t,n)}},function(t,n){var r=0,e=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++r+e).toString(36))}},function(t,n,r){var e=r(33);t.exports=function(t){return Object(e(t))}},function(t,n,r){var e=r(7)("unscopables"),i=Array.prototype;void 0==i[e]&&r(27)(i,e,{}),t.exports=function(t){i[e][t]=!0}},function(t,n,r){var e=r(53),i=r(169),o=r(137),u=r(2),c=r(16),f=r(154),a={},s={},n=t.exports=function(t,n,r,l,h){var v,p,d,y,g=h?function(){return t}:f(t),b=e(r,l,n?2:1),m=0;if("function"!=typeof g)throw TypeError(t+" is not iterable!");if(o(g)){for(v=c(t.length);v>m;m++)if((y=n?b(u(p=t[m])[0],p[1]):b(t[m]))===a||y===s)return y}else for(d=g.call(t);!(p=d.next()).done;)if((y=i(d,b,p.value,n))===a||y===s)return y};n.BREAK=a,n.RETURN=s},function(t,n){t.exports={}},function(t,n,r){var e=r(11).f,i=r(24),o=r(7)("toStringTag");t.exports=function(t,n,r){t&&!i(t=r?t:t.prototype,o)&&e(t,o,{configurable:!0,value:n})}},function(t,n,r){var e=r(1),i=r(46),o=r(4),u=r(150),c="["+u+"]",f="​",a=RegExp("^"+c+c+"*"),s=RegExp(c+c+"*$"),l=function(t,n,r){var i={},c=o(function(){return!!u[t]()||f[t]()!=f}),a=i[t]=c?n(h):u[t];r&&(i[r]=a),e(e.P+e.F*c,"String",i)},h=l.trim=function(t,n){return t=String(i(t)),1&n&&(t=t.replace(a,"")),2&n&&(t=t.replace(s,"")),t};t.exports=l},function(t,n,r){t.exports={default:r(86),__esModule:!0}},function(t,n,r){t.exports={default:r(87),__esModule:!0}},function(t,n,r){"use strict";function e(t){return t&&t.__esModule?t:{default:t}}n.__esModule=!0;var i=r(84),o=e(i),u=r(83),c=e(u),f="function"==typeof c.default&&"symbol"==typeof o.default?function(t){return typeof t}:function(t){return t&&"function"==typeof c.default&&t.constructor===c.default&&t!==c.default.prototype?"symbol":typeof t};n.default="function"==typeof c.default&&"symbol"===f(o.default)?function(t){return void 0===t?"undefined":f(t)}:function(t){return t&&"function"==typeof c.default&&t.constructor===c.default&&t!==c.default.prototype?"symbol":void 0===t?"undefined":f(t)}},function(t,n,r){r(110),r(108),r(111),r(112),t.exports=r(25).Symbol},function(t,n,r){r(109),r(113),t.exports=r(44).f("iterator")},function(t,n){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},function(t,n){t.exports=function(){}},function(t,n,r){var e=r(9),i=r(106),o=r(105);t.exports=function(t){return function(n,r,u){var c,f=e(n),a=i(f.length),s=o(u,a);if(t&&r!=r){for(;a>s;)if((c=f[s++])!=c)return!0}else for(;a>s;s++)if((t||s in f)&&f[s]===r)return t||s||0;return!t&&-1}}},function(t,n,r){var e=r(88);t.exports=function(t,n,r){if(e(t),void 0===n)return t;switch(r){case 1:return function(r){return t.call(n,r)};case 2:return function(r,e){return t.call(n,r,e)};case 3:return function(r,e,i){return t.call(n,r,e,i)}}return function(){return t.apply(n,arguments)}}},function(t,n,r){var e=r(19),i=r(62),o=r(37);t.exports=function(t){var n=e(t),r=i.f;if(r)for(var u,c=r(t),f=o.f,a=0;c.length>a;)f.call(t,u=c[a++])&&n.push(u);return n}},function(t,n,r){t.exports=r(5).document&&document.documentElement},function(t,n,r){var e=r(56);t.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==e(t)?t.split(""):Object(t)}},function(t,n,r){var e=r(56);t.exports=Array.isArray||function(t){return"Array"==e(t)}},function(t,n,r){"use strict";var e=r(60),i=r(22),o=r(38),u={};r(13)(u,r(15)("iterator"),function(){return this}),t.exports=function(t,n,r){t.prototype=e(u,{next:i(1,r)}),o(t,n+" Iterator")}},function(t,n){t.exports=function(t,n){return{value:n,done:!!t}}},function(t,n,r){var e=r(19),i=r(9);t.exports=function(t,n){for(var r,o=i(t),u=e(o),c=u.length,f=0;c>f;)if(o[r=u[f++]]===n)return r}},function(t,n,r){var e=r(23)("meta"),i=r(21),o=r(8),u=r(14).f,c=0,f=Object.isExtensible||function(){return!0},a=!r(18)(function(){return f(Object.preventExtensions({}))}),s=function(t){u(t,e,{value:{i:"O"+ ++c,w:{}}})},l=function(t,n){if(!i(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!o(t,e)){if(!f(t))return"F";if(!n)return"E";s(t)}return t[e].i},h=function(t,n){if(!o(t,e)){if(!f(t))return!0;if(!n)return!1;s(t)}return t[e].w},v=function(t){return a&&p.NEED&&f(t)&&!o(t,e)&&s(t),t},p=t.exports={KEY:e,NEED:!1,fastKey:l,getWeak:h,onFreeze:v}},function(t,n,r){var e=r(14),i=r(20),o=r(19);t.exports=r(12)?Object.defineProperties:function(t,n){i(t);for(var r,u=o(n),c=u.length,f=0;c>f;)e.f(t,r=u[f++],n[r]);return t}},function(t,n,r){var e=r(37),i=r(22),o=r(9),u=r(42),c=r(8),f=r(58),a=Object.getOwnPropertyDescriptor;n.f=r(12)?a:function(t,n){if(t=o(t),n=u(n,!0),f)try{return a(t,n)}catch(t){}if(c(t,n))return i(!e.f.call(t,n),t[n])}},function(t,n,r){var e=r(9),i=r(61).f,o={}.toString,u="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],c=function(t){try{return i(t)}catch(t){return u.slice()}};t.exports.f=function(t){return u&&"[object Window]"==o.call(t)?c(t):i(e(t))}},function(t,n,r){var e=r(8),i=r(77),o=r(39)("IE_PROTO"),u=Object.prototype;t.exports=Object.getPrototypeOf||function(t){return t=i(t),e(t,o)?t[o]:"function"==typeof t.constructor&&t instanceof t.constructor?t.constructor.prototype:t instanceof Object?u:null}},function(t,n,r){var e=r(41),i=r(33);t.exports=function(t){return function(n,r){var o,u,c=String(i(n)),f=e(r),a=c.length;return f<0||f>=a?t?"":void 0:(o=c.charCodeAt(f),o<55296||o>56319||f+1===a||(u=c.charCodeAt(f+1))<56320||u>57343?t?c.charAt(f):o:t?c.slice(f,f+2):u-56320+(o-55296<<10)+65536)}}},function(t,n,r){var e=r(41),i=Math.max,o=Math.min;t.exports=function(t,n){return t=e(t),t<0?i(t+n,0):o(t,n)}},function(t,n,r){var e=r(41),i=Math.min;t.exports=function(t){return t>0?i(e(t),9007199254740991):0}},function(t,n,r){"use strict";var e=r(89),i=r(97),o=r(35),u=r(9);t.exports=r(59)(Array,"Array",function(t,n){this._t=u(t),this._i=0,this._k=n},function(){var t=this._t,n=this._k,r=this._i++;return!t||r>=t.length?(this._t=void 0,i(1)):"keys"==n?i(0,r):"values"==n?i(0,t[r]):i(0,[r,t[r]])},"values"),o.Arguments=o.Array,e("keys"),e("values"),e("entries")},function(t,n){},function(t,n,r){"use strict";var e=r(104)(!0);r(59)(String,"String",function(t){this._t=String(t),this._i=0},function(){var t,n=this._t,r=this._i;return r>=n.length?{value:void 0,done:!0}:(t=e(n,r),this._i+=t.length,{value:t,done:!1})})},function(t,n,r){"use strict";var e=r(5),i=r(8),o=r(12),u=r(51),c=r(64),f=r(99).KEY,a=r(18),s=r(40),l=r(38),h=r(23),v=r(15),p=r(44),d=r(43),y=r(98),g=r(92),b=r(95),m=r(20),x=r(9),w=r(42),S=r(22),_=r(60),O=r(102),E=r(101),P=r(14),j=r(19),F=E.f,M=P.f,A=O.f,N=e.Symbol,T=e.JSON,I=T&&T.stringify,k="prototype",L=v("_hidden"),R=v("toPrimitive"),C={}.propertyIsEnumerable,D=s("symbol-registry"),U=s("symbols"),W=s("op-symbols"),G=Object[k],B="function"==typeof N,V=e.QObject,z=!V||!V[k]||!V[k].findChild,q=o&&a(function(){return 7!=_(M({},"a",{get:function(){return M(this,"a",{value:7}).a}})).a})?function(t,n,r){var e=F(G,n);e&&delete G[n],M(t,n,r),e&&t!==G&&M(G,n,e)}:M,K=function(t){var n=U[t]=_(N[k]);return n._k=t,n},J=B&&"symbol"==typeof N.iterator?function(t){return"symbol"==typeof t}:function(t){return t instanceof N},Y=function(t,n,r){return t===G&&Y(W,n,r),m(t),n=w(n,!0),m(r),i(U,n)?(r.enumerable?(i(t,L)&&t[L][n]&&(t[L][n]=!1),r=_(r,{enumerable:S(0,!1)})):(i(t,L)||M(t,L,S(1,{})),t[L][n]=!0),q(t,n,r)):M(t,n,r)},H=function(t,n){m(t);for(var r,e=g(n=x(n)),i=0,o=e.length;o>i;)Y(t,r=e[i++],n[r]);return t},$=function(t,n){return void 0===n?_(t):H(_(t),n)},X=function(t){var n=C.call(this,t=w(t,!0));return!(this===G&&i(U,t)&&!i(W,t))&&(!(n||!i(this,t)||!i(U,t)||i(this,L)&&this[L][t])||n)},Q=function(t,n){if(t=x(t),n=w(n,!0),t!==G||!i(U,n)||i(W,n)){var r=F(t,n);return!r||!i(U,n)||i(t,L)&&t[L][n]||(r.enumerable=!0),r}},Z=function(t){for(var n,r=A(x(t)),e=[],o=0;r.length>o;)i(U,n=r[o++])||n==L||n==f||e.push(n);return e},tt=function(t){for(var n,r=t===G,e=A(r?W:x(t)),o=[],u=0;e.length>u;)!i(U,n=e[u++])||r&&!i(G,n)||o.push(U[n]);return o};B||(N=function(){if(this instanceof N)throw TypeError("Symbol is not a constructor!");var t=h(arguments.length>0?arguments[0]:void 0),n=function(r){this===G&&n.call(W,r),i(this,L)&&i(this[L],t)&&(this[L][t]=!1),q(this,t,S(1,r))};return o&&z&&q(G,t,{configurable:!0,set:n}),K(t)},c(N[k],"toString",function(){return this._k}),E.f=Q,P.f=Y,r(61).f=O.f=Z,r(37).f=X,r(62).f=tt,o&&!r(36)&&c(G,"propertyIsEnumerable",X,!0),p.f=function(t){return K(v(t))}),u(u.G+u.W+u.F*!B,{Symbol:N});for(var nt="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),rt=0;nt.length>rt;)v(nt[rt++]);for(var nt=j(v.store),rt=0;nt.length>rt;)d(nt[rt++]);u(u.S+u.F*!B,"Symbol",{for:function(t){return i(D,t+="")?D[t]:D[t]=N(t)},keyFor:function(t){if(J(t))return y(D,t);throw TypeError(t+" is not a symbol!")},useSetter:function(){z=!0},useSimple:function(){z=!1}}),u(u.S+u.F*!B,"Object",{create:$,defineProperty:Y,defineProperties:H,getOwnPropertyDescriptor:Q,getOwnPropertyNames:Z,getOwnPropertySymbols:tt}),T&&u(u.S+u.F*(!B||a(function(){var t=N();return"[null]"!=I([t])||"{}"!=I({a:t})||"{}"!=I(Object(t))})),"JSON",{stringify:function(t){if(void 0!==t&&!J(t)){for(var n,r,e=[t],i=1;arguments.length>i;)e.push(arguments[i++]);return n=e[1],"function"==typeof n&&(r=n),!r&&b(n)||(n=function(t,n){if(r&&(n=r.call(this,t,n)),!J(n))return n}),e[1]=n,I.apply(T,e)}}}),N[k][R]||r(13)(N[k],R,N[k].valueOf),l(N,"Symbol"),l(Math,"Math",!0),l(e.JSON,"JSON",!0)},function(t,n,r){r(43)("asyncIterator")},function(t,n,r){r(43)("observable")},function(t,n,r){r(107);for(var e=r(5),i=r(13),o=r(35),u=r(15)("toStringTag"),c=["NodeList","DOMTokenList","MediaList","StyleSheetList","CSSRuleList"],f=0;f<5;f++){var a=c[f],s=e[a],l=s&&s.prototype;l&&!l[u]&&i(l,u,a),o[a]=o.Array}},function(t,n,r){var e=r(45),i=r(7)("toStringTag"),o="Arguments"==e(function(){return arguments}()),u=function(t,n){try{return t[n]}catch(t){}};t.exports=function(t){var n,r,c;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(r=u(n=Object(t),i))?r:o?e(n):"Object"==(c=e(n))&&"function"==typeof n.callee?"Arguments":c}},function(t,n,r){var e=r(45);t.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==e(t)?t.split(""):Object(t)}},function(t,n){n.f={}.propertyIsEnumerable},function(t,n,r){var e=r(30),i=r(16),o=r(75);t.exports=function(t){return function(n,r,u){var c,f=e(n),a=i(f.length),s=o(u,a);if(t&&r!=r){for(;a>s;)if((c=f[s++])!=c)return!0}else for(;a>s;s++)if((t||s in f)&&f[s]===r)return t||s||0;return!t&&-1}}},function(t,n,r){"use strict";var e=r(3),i=r(1),o=r(28),u=r(73),c=r(65),f=r(79),a=r(68),s=r(6),l=r(4),h=r(123),v=r(81),p=r(136);t.exports=function(t,n,r,d,y,g){var b=e[t],m=b,x=y?"set":"add",w=m&&m.prototype,S={},_=function(t){var n=w[t];o(w,t,"delete"==t?function(t){return!(g&&!s(t))&&n.call(this,0===t?0:t)}:"has"==t?function(t){return!(g&&!s(t))&&n.call(this,0===t?0:t)}:"get"==t?function(t){return g&&!s(t)?void 0:n.call(this,0===t?0:t)}:"add"==t?function(t){return n.call(this,0===t?0:t),this}:function(t,r){return n.call(this,0===t?0:t,r),this})};if("function"==typeof m&&(g||w.forEach&&!l(function(){(new m).entries().next()}))){var O=new m,E=O[x](g?{}:-0,1)!=O,P=l(function(){O.has(1)}),j=h(function(t){new m(t)}),F=!g&&l(function(){for(var t=new m,n=5;n--;)t[x](n,n);return!t.has(-0)});j||(m=n(function(n,r){a(n,m,t);var e=p(new b,n,m);return void 0!=r&&f(r,y,e[x],e),e}),m.prototype=w,w.constructor=m),(P||F)&&(_("delete"),_("has"),y&&_("get")),(F||E)&&_(x),g&&w.clear&&delete w.clear}else m=d.getConstructor(n,t,y,x),u(m.prototype,r),c.NEED=!0;return v(m,t),S[t]=m,i(i.G+i.W+i.F*(m!=b),S),g||d.setStrong(m,t,y),m}},function(t,n,r){"use strict";var e=r(27),i=r(28),o=r(4),u=r(46),c=r(7);t.exports=function(t,n,r){var f=c(t),a=r(u,f,""[t]),s=a[0],l=a[1];o(function(){var n={};return n[f]=function(){return 7},7!=""[t](n)})&&(i(String.prototype,t,s),e(RegExp.prototype,f,2==n?function(t,n){return l.call(t,this,n)}:function(t){return l.call(t,this)}))}
},function(t,n,r){"use strict";var e=r(2);t.exports=function(){var t=e(this),n="";return t.global&&(n+="g"),t.ignoreCase&&(n+="i"),t.multiline&&(n+="m"),t.unicode&&(n+="u"),t.sticky&&(n+="y"),n}},function(t,n){t.exports=function(t,n,r){var e=void 0===r;switch(n.length){case 0:return e?t():t.call(r);case 1:return e?t(n[0]):t.call(r,n[0]);case 2:return e?t(n[0],n[1]):t.call(r,n[0],n[1]);case 3:return e?t(n[0],n[1],n[2]):t.call(r,n[0],n[1],n[2]);case 4:return e?t(n[0],n[1],n[2],n[3]):t.call(r,n[0],n[1],n[2],n[3])}return t.apply(r,n)}},function(t,n,r){var e=r(6),i=r(45),o=r(7)("match");t.exports=function(t){var n;return e(t)&&(void 0!==(n=t[o])?!!n:"RegExp"==i(t))}},function(t,n,r){var e=r(7)("iterator"),i=!1;try{var o=[7][e]();o.return=function(){i=!0},Array.from(o,function(){throw 2})}catch(t){}t.exports=function(t,n){if(!n&&!i)return!1;var r=!1;try{var o=[7],u=o[e]();u.next=function(){return{done:r=!0}},o[e]=function(){return u},t(o)}catch(t){}return r}},function(t,n,r){t.exports=r(69)||!r(4)(function(){var t=Math.random();__defineSetter__.call(null,t,function(){}),delete r(3)[t]})},function(t,n){n.f=Object.getOwnPropertySymbols},function(t,n,r){var e=r(3),i="__core-js_shared__",o=e[i]||(e[i]={});t.exports=function(t){return o[t]||(o[t]={})}},function(t,n,r){for(var e,i=r(3),o=r(27),u=r(76),c=u("typed_array"),f=u("view"),a=!(!i.ArrayBuffer||!i.DataView),s=a,l=0,h="Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array".split(",");l<9;)(e=i[h[l++]])?(o(e.prototype,c,!0),o(e.prototype,f,!0)):s=!1;t.exports={ABV:a,CONSTR:s,TYPED:c,VIEW:f}},function(t,n){"use strict";var r={versions:function(){var t=window.navigator.userAgent;return{trident:t.indexOf("Trident")>-1,presto:t.indexOf("Presto")>-1,webKit:t.indexOf("AppleWebKit")>-1,gecko:t.indexOf("Gecko")>-1&&-1==t.indexOf("KHTML"),mobile:!!t.match(/AppleWebKit.*Mobile.*/),ios:!!t.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),android:t.indexOf("Android")>-1||t.indexOf("Linux")>-1,iPhone:t.indexOf("iPhone")>-1||t.indexOf("Mac")>-1,iPad:t.indexOf("iPad")>-1,webApp:-1==t.indexOf("Safari"),weixin:-1==t.indexOf("MicroMessenger")}}()};t.exports=r},function(t,n,r){"use strict";var e=r(85),i=function(t){return t&&t.__esModule?t:{default:t}}(e),o=function(){function t(t,n,e){return n||e?String.fromCharCode(n||e):r[t]||t}function n(t){return e[t]}var r={"&quot;":'"',"&lt;":"<","&gt;":">","&amp;":"&","&nbsp;":" "},e={};for(var u in r)e[r[u]]=u;return r["&apos;"]="'",e["'"]="&#39;",{encode:function(t){return t?(""+t).replace(/['<> "&]/g,n).replace(/\r?\n/g,"<br/>").replace(/\s/g,"&nbsp;"):""},decode:function(n){return n?(""+n).replace(/<br\s*\/?>/gi,"\n").replace(/&quot;|&lt;|&gt;|&amp;|&nbsp;|&apos;|&#(\d+);|&#(\d+)/g,t).replace(/\u00a0/g," "):""},encodeBase16:function(t){if(!t)return t;t+="";for(var n=[],r=0,e=t.length;e>r;r++)n.push(t.charCodeAt(r).toString(16).toUpperCase());return n.join("")},encodeBase16forJSON:function(t){if(!t)return t;t=t.replace(/[\u4E00-\u9FBF]/gi,function(t){return escape(t).replace("%u","\\u")});for(var n=[],r=0,e=t.length;e>r;r++)n.push(t.charCodeAt(r).toString(16).toUpperCase());return n.join("")},decodeBase16:function(t){if(!t)return t;t+="";for(var n=[],r=0,e=t.length;e>r;r+=2)n.push(String.fromCharCode("0x"+t.slice(r,r+2)));return n.join("")},encodeObject:function(t){if(t instanceof Array)for(var n=0,r=t.length;r>n;n++)t[n]=o.encodeObject(t[n]);else if("object"==(void 0===t?"undefined":(0,i.default)(t)))for(var e in t)t[e]=o.encodeObject(t[e]);else if("string"==typeof t)return o.encode(t);return t},loadScript:function(t){var n=document.createElement("script");document.getElementsByTagName("body")[0].appendChild(n),n.setAttribute("src",t)},addLoadEvent:function(t){var n=window.onload;"function"!=typeof window.onload?window.onload=t:window.onload=function(){n(),t()}}}}();t.exports=o},function(t,n,r){"use strict";var e=r(17),i=r(75),o=r(16);t.exports=function(t){for(var n=e(this),r=o(n.length),u=arguments.length,c=i(u>1?arguments[1]:void 0,r),f=u>2?arguments[2]:void 0,a=void 0===f?r:i(f,r);a>c;)n[c++]=t;return n}},function(t,n,r){"use strict";var e=r(11),i=r(66);t.exports=function(t,n,r){n in t?e.f(t,n,i(0,r)):t[n]=r}},function(t,n,r){var e=r(6),i=r(3).document,o=e(i)&&e(i.createElement);t.exports=function(t){return o?i.createElement(t):{}}},function(t,n){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(t,n,r){var e=r(7)("match");t.exports=function(t){var n=/./;try{"/./"[t](n)}catch(r){try{return n[e]=!1,!"/./"[t](n)}catch(t){}}return!0}},function(t,n,r){t.exports=r(3).document&&document.documentElement},function(t,n,r){var e=r(6),i=r(144).set;t.exports=function(t,n,r){var o,u=n.constructor;return u!==r&&"function"==typeof u&&(o=u.prototype)!==r.prototype&&e(o)&&i&&i(t,o),t}},function(t,n,r){var e=r(80),i=r(7)("iterator"),o=Array.prototype;t.exports=function(t){return void 0!==t&&(e.Array===t||o[i]===t)}},function(t,n,r){var e=r(45);t.exports=Array.isArray||function(t){return"Array"==e(t)}},function(t,n,r){"use strict";var e=r(70),i=r(66),o=r(81),u={};r(27)(u,r(7)("iterator"),function(){return this}),t.exports=function(t,n,r){t.prototype=e(u,{next:i(1,r)}),o(t,n+" Iterator")}},function(t,n,r){"use strict";var e=r(69),i=r(1),o=r(28),u=r(27),c=r(24),f=r(80),a=r(139),s=r(81),l=r(32),h=r(7)("iterator"),v=!([].keys&&"next"in[].keys()),p="keys",d="values",y=function(){return this};t.exports=function(t,n,r,g,b,m,x){a(r,n,g);var w,S,_,O=function(t){if(!v&&t in F)return F[t];switch(t){case p:case d:return function(){return new r(this,t)}}return function(){return new r(this,t)}},E=n+" Iterator",P=b==d,j=!1,F=t.prototype,M=F[h]||F["@@iterator"]||b&&F[b],A=M||O(b),N=b?P?O("entries"):A:void 0,T="Array"==n?F.entries||M:M;if(T&&(_=l(T.call(new t)))!==Object.prototype&&(s(_,E,!0),e||c(_,h)||u(_,h,y)),P&&M&&M.name!==d&&(j=!0,A=function(){return M.call(this)}),e&&!x||!v&&!j&&F[h]||u(F,h,A),f[n]=A,f[E]=y,b)if(w={values:P?A:O(d),keys:m?A:O(p),entries:N},x)for(S in w)S in F||o(F,S,w[S]);else i(i.P+i.F*(v||j),n,w);return w}},function(t,n){var r=Math.expm1;t.exports=!r||r(10)>22025.465794806718||r(10)<22025.465794806718||-2e-17!=r(-2e-17)?function(t){return 0==(t=+t)?t:t>-1e-6&&t<1e-6?t+t*t/2:Math.exp(t)-1}:r},function(t,n){t.exports=Math.sign||function(t){return 0==(t=+t)||t!=t?t:t<0?-1:1}},function(t,n,r){var e=r(3),i=r(151).set,o=e.MutationObserver||e.WebKitMutationObserver,u=e.process,c=e.Promise,f="process"==r(45)(u);t.exports=function(){var t,n,r,a=function(){var e,i;for(f&&(e=u.domain)&&e.exit();t;){i=t.fn,t=t.next;try{i()}catch(e){throw t?r():n=void 0,e}}n=void 0,e&&e.enter()};if(f)r=function(){u.nextTick(a)};else if(o){var s=!0,l=document.createTextNode("");new o(a).observe(l,{characterData:!0}),r=function(){l.data=s=!s}}else if(c&&c.resolve){var h=c.resolve();r=function(){h.then(a)}}else r=function(){i.call(e,a)};return function(e){var i={fn:e,next:void 0};n&&(n.next=i),t||(t=i,r()),n=i}}},function(t,n,r){var e=r(6),i=r(2),o=function(t,n){if(i(t),!e(n)&&null!==n)throw TypeError(n+": can't set as prototype!")};t.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(t,n,e){try{e=r(53)(Function.call,r(31).f(Object.prototype,"__proto__").set,2),e(t,[]),n=!(t instanceof Array)}catch(t){n=!0}return function(t,r){return o(t,r),n?t.__proto__=r:e(t,r),t}}({},!1):void 0),check:o}},function(t,n,r){var e=r(126)("keys"),i=r(76);t.exports=function(t){return e[t]||(e[t]=i(t))}},function(t,n,r){var e=r(2),i=r(26),o=r(7)("species");t.exports=function(t,n){var r,u=e(t).constructor;return void 0===u||void 0==(r=e(u)[o])?n:i(r)}},function(t,n,r){var e=r(67),i=r(46);t.exports=function(t){return function(n,r){var o,u,c=String(i(n)),f=e(r),a=c.length;return f<0||f>=a?t?"":void 0:(o=c.charCodeAt(f),o<55296||o>56319||f+1===a||(u=c.charCodeAt(f+1))<56320||u>57343?t?c.charAt(f):o:t?c.slice(f,f+2):u-56320+(o-55296<<10)+65536)}}},function(t,n,r){var e=r(122),i=r(46);t.exports=function(t,n,r){if(e(n))throw TypeError("String#"+r+" doesn't accept regex!");return String(i(t))}},function(t,n,r){"use strict";var e=r(67),i=r(46);t.exports=function(t){var n=String(i(this)),r="",o=e(t);if(o<0||o==1/0)throw RangeError("Count can't be negative");for(;o>0;(o>>>=1)&&(n+=n))1&o&&(r+=n);return r}},function(t,n){t.exports="\t\n\v\f\r   ᠎             　\u2028\u2029\ufeff"},function(t,n,r){var e,i,o,u=r(53),c=r(121),f=r(135),a=r(132),s=r(3),l=s.process,h=s.setImmediate,v=s.clearImmediate,p=s.MessageChannel,d=0,y={},g="onreadystatechange",b=function(){var t=+this;if(y.hasOwnProperty(t)){var n=y[t];delete y[t],n()}},m=function(t){b.call(t.data)};h&&v||(h=function(t){for(var n=[],r=1;arguments.length>r;)n.push(arguments[r++]);return y[++d]=function(){c("function"==typeof t?t:Function(t),n)},e(d),d},v=function(t){delete y[t]},"process"==r(45)(l)?e=function(t){l.nextTick(u(b,t,1))}:p?(i=new p,o=i.port2,i.port1.onmessage=m,e=u(o.postMessage,o,1)):s.addEventListener&&"function"==typeof postMessage&&!s.importScripts?(e=function(t){s.postMessage(t+"","*")},s.addEventListener("message",m,!1)):e=g in a("script")?function(t){f.appendChild(a("script"))[g]=function(){f.removeChild(this),b.call(t)}}:function(t){setTimeout(u(b,t,1),0)}),t.exports={set:h,clear:v}},function(t,n,r){"use strict";var e=r(3),i=r(10),o=r(69),u=r(127),c=r(27),f=r(73),a=r(4),s=r(68),l=r(67),h=r(16),v=r(71).f,p=r(11).f,d=r(130),y=r(81),g="ArrayBuffer",b="DataView",m="prototype",x="Wrong length!",w="Wrong index!",S=e[g],_=e[b],O=e.Math,E=e.RangeError,P=e.Infinity,j=S,F=O.abs,M=O.pow,A=O.floor,N=O.log,T=O.LN2,I="buffer",k="byteLength",L="byteOffset",R=i?"_b":I,C=i?"_l":k,D=i?"_o":L,U=function(t,n,r){var e,i,o,u=Array(r),c=8*r-n-1,f=(1<<c)-1,a=f>>1,s=23===n?M(2,-24)-M(2,-77):0,l=0,h=t<0||0===t&&1/t<0?1:0;for(t=F(t),t!=t||t===P?(i=t!=t?1:0,e=f):(e=A(N(t)/T),t*(o=M(2,-e))<1&&(e--,o*=2),t+=e+a>=1?s/o:s*M(2,1-a),t*o>=2&&(e++,o/=2),e+a>=f?(i=0,e=f):e+a>=1?(i=(t*o-1)*M(2,n),e+=a):(i=t*M(2,a-1)*M(2,n),e=0));n>=8;u[l++]=255&i,i/=256,n-=8);for(e=e<<n|i,c+=n;c>0;u[l++]=255&e,e/=256,c-=8);return u[--l]|=128*h,u},W=function(t,n,r){var e,i=8*r-n-1,o=(1<<i)-1,u=o>>1,c=i-7,f=r-1,a=t[f--],s=127&a;for(a>>=7;c>0;s=256*s+t[f],f--,c-=8);for(e=s&(1<<-c)-1,s>>=-c,c+=n;c>0;e=256*e+t[f],f--,c-=8);if(0===s)s=1-u;else{if(s===o)return e?NaN:a?-P:P;e+=M(2,n),s-=u}return(a?-1:1)*e*M(2,s-n)},G=function(t){return t[3]<<24|t[2]<<16|t[1]<<8|t[0]},B=function(t){return[255&t]},V=function(t){return[255&t,t>>8&255]},z=function(t){return[255&t,t>>8&255,t>>16&255,t>>24&255]},q=function(t){return U(t,52,8)},K=function(t){return U(t,23,4)},J=function(t,n,r){p(t[m],n,{get:function(){return this[r]}})},Y=function(t,n,r,e){var i=+r,o=l(i);if(i!=o||o<0||o+n>t[C])throw E(w);var u=t[R]._b,c=o+t[D],f=u.slice(c,c+n);return e?f:f.reverse()},H=function(t,n,r,e,i,o){var u=+r,c=l(u);if(u!=c||c<0||c+n>t[C])throw E(w);for(var f=t[R]._b,a=c+t[D],s=e(+i),h=0;h<n;h++)f[a+h]=s[o?h:n-h-1]},$=function(t,n){s(t,S,g);var r=+n,e=h(r);if(r!=e)throw E(x);return e};if(u.ABV){if(!a(function(){new S})||!a(function(){new S(.5)})){S=function(t){return new j($(this,t))};for(var X,Q=S[m]=j[m],Z=v(j),tt=0;Z.length>tt;)(X=Z[tt++])in S||c(S,X,j[X]);o||(Q.constructor=S)}var nt=new _(new S(2)),rt=_[m].setInt8;nt.setInt8(0,2147483648),nt.setInt8(1,2147483649),!nt.getInt8(0)&&nt.getInt8(1)||f(_[m],{setInt8:function(t,n){rt.call(this,t,n<<24>>24)},setUint8:function(t,n){rt.call(this,t,n<<24>>24)}},!0)}else S=function(t){var n=$(this,t);this._b=d.call(Array(n),0),this[C]=n},_=function(t,n,r){s(this,_,b),s(t,S,b);var e=t[C],i=l(n);if(i<0||i>e)throw E("Wrong offset!");if(r=void 0===r?e-i:h(r),i+r>e)throw E(x);this[R]=t,this[D]=i,this[C]=r},i&&(J(S,k,"_l"),J(_,I,"_b"),J(_,k,"_l"),J(_,L,"_o")),f(_[m],{getInt8:function(t){return Y(this,1,t)[0]<<24>>24},getUint8:function(t){return Y(this,1,t)[0]},getInt16:function(t){var n=Y(this,2,t,arguments[1]);return(n[1]<<8|n[0])<<16>>16},getUint16:function(t){var n=Y(this,2,t,arguments[1]);return n[1]<<8|n[0]},getInt32:function(t){return G(Y(this,4,t,arguments[1]))},getUint32:function(t){return G(Y(this,4,t,arguments[1]))>>>0},getFloat32:function(t){return W(Y(this,4,t,arguments[1]),23,4)},getFloat64:function(t){return W(Y(this,8,t,arguments[1]),52,8)},setInt8:function(t,n){H(this,1,t,B,n)},setUint8:function(t,n){H(this,1,t,B,n)},setInt16:function(t,n){H(this,2,t,V,n,arguments[2])},setUint16:function(t,n){H(this,2,t,V,n,arguments[2])},setInt32:function(t,n){H(this,4,t,z,n,arguments[2])},setUint32:function(t,n){H(this,4,t,z,n,arguments[2])},setFloat32:function(t,n){H(this,4,t,K,n,arguments[2])},setFloat64:function(t,n){H(this,8,t,q,n,arguments[2])}});y(S,g),y(_,b),c(_[m],u.VIEW,!0),n[g]=S,n[b]=_},function(t,n,r){var e=r(3),i=r(52),o=r(69),u=r(182),c=r(11).f;t.exports=function(t){var n=i.Symbol||(i.Symbol=o?{}:e.Symbol||{});"_"==t.charAt(0)||t in n||c(n,t,{value:u.f(t)})}},function(t,n,r){var e=r(114),i=r(7)("iterator"),o=r(80);t.exports=r(52).getIteratorMethod=function(t){if(void 0!=t)return t[i]||t["@@iterator"]||o[e(t)]}},function(t,n,r){"use strict";var e=r(78),i=r(170),o=r(80),u=r(30);t.exports=r(140)(Array,"Array",function(t,n){this._t=u(t),this._i=0,this._k=n},function(){var t=this._t,n=this._k,r=this._i++;return!t||r>=t.length?(this._t=void 0,i(1)):"keys"==n?i(0,r):"values"==n?i(0,t[r]):i(0,[r,t[r]])},"values"),o.Arguments=o.Array,e("keys"),e("values"),e("entries")},function(t,n){function r(t,n){t.classList?t.classList.add(n):t.className+=" "+n}t.exports=r},function(t,n){function r(t,n){if(t.classList)t.classList.remove(n);else{var r=new RegExp("(^|\\b)"+n.split(" ").join("|")+"(\\b|$)","gi");t.className=t.className.replace(r," ")}}t.exports=r},function(t,n){function r(){throw new Error("setTimeout has not been defined")}function e(){throw new Error("clearTimeout has not been defined")}function i(t){if(s===setTimeout)return setTimeout(t,0);if((s===r||!s)&&setTimeout)return s=setTimeout,setTimeout(t,0);try{return s(t,0)}catch(n){try{return s.call(null,t,0)}catch(n){return s.call(this,t,0)}}}function o(t){if(l===clearTimeout)return clearTimeout(t);if((l===e||!l)&&clearTimeout)return l=clearTimeout,clearTimeout(t);try{return l(t)}catch(n){try{return l.call(null,t)}catch(n){return l.call(this,t)}}}function u(){d&&v&&(d=!1,v.length?p=v.concat(p):y=-1,p.length&&c())}function c(){if(!d){var t=i(u);d=!0;for(var n=p.length;n;){for(v=p,p=[];++y<n;)v&&v[y].run();y=-1,n=p.length}v=null,d=!1,o(t)}}function f(t,n){this.fun=t,this.array=n}function a(){}var s,l,h=t.exports={};!function(){try{s="function"==typeof setTimeout?setTimeout:r}catch(t){s=r}try{l="function"==typeof clearTimeout?clearTimeout:e}catch(t){l=e}}();var v,p=[],d=!1,y=-1;h.nextTick=function(t){var n=new Array(arguments.length-1);if(arguments.length>1)for(var r=1;r<arguments.length;r++)n[r-1]=arguments[r];p.push(new f(t,n)),1!==p.length||d||i(c)},f.prototype.run=function(){this.fun.apply(null,this.array)},h.title="browser",h.browser=!0,h.env={},h.argv=[],h.version="",h.versions={},h.on=a,h.addListener=a,h.once=a,h.off=a,h.removeListener=a,h.removeAllListeners=a,h.emit=a,h.prependListener=a,h.prependOnceListener=a,h.listeners=function(t){return[]},h.binding=function(t){throw new Error("process.binding is not supported")},h.cwd=function(){return"/"},h.chdir=function(t){throw new Error("process.chdir is not supported")},h.umask=function(){return 0}},function(t,n,r){var e=r(45);t.exports=function(t,n){if("number"!=typeof t&&"Number"!=e(t))throw TypeError(n);return+t}},function(t,n,r){"use strict";var e=r(17),i=r(75),o=r(16);t.exports=[].copyWithin||function(t,n){var r=e(this),u=o(r.length),c=i(t,u),f=i(n,u),a=arguments.length>2?arguments[2]:void 0,s=Math.min((void 0===a?u:i(a,u))-f,u-c),l=1;for(f<c&&c<f+s&&(l=-1,f+=s-1,c+=s-1);s-- >0;)f in r?r[c]=r[f]:delete r[c],c+=l,f+=l;return r}},function(t,n,r){var e=r(79);t.exports=function(t,n){var r=[];return e(t,!1,r.push,r,n),r}},function(t,n,r){var e=r(26),i=r(17),o=r(115),u=r(16);t.exports=function(t,n,r,c,f){e(n);var a=i(t),s=o(a),l=u(a.length),h=f?l-1:0,v=f?-1:1;if(r<2)for(;;){if(h in s){c=s[h],h+=v;break}if(h+=v,f?h<0:l<=h)throw TypeError("Reduce of empty array with no initial value")}for(;f?h>=0:l>h;h+=v)h in s&&(c=n(c,s[h],h,a));return c}},function(t,n,r){"use strict";var e=r(26),i=r(6),o=r(121),u=[].slice,c={},f=function(t,n,r){if(!(n in c)){for(var e=[],i=0;i<n;i++)e[i]="a["+i+"]";c[n]=Function("F,a","return new F("+e.join(",")+")")}return c[n](t,r)};t.exports=Function.bind||function(t){var n=e(this),r=u.call(arguments,1),c=function(){var e=r.concat(u.call(arguments));return this instanceof c?f(n,e.length,e):o(n,e,t)};return i(n.prototype)&&(c.prototype=n.prototype),c}},function(t,n,r){"use strict";var e=r(11).f,i=r(70),o=r(73),u=r(53),c=r(68),f=r(46),a=r(79),s=r(140),l=r(170),h=r(74),v=r(10),p=r(65).fastKey,d=v?"_s":"size",y=function(t,n){var r,e=p(n);if("F"!==e)return t._i[e];for(r=t._f;r;r=r.n)if(r.k==n)return r};t.exports={getConstructor:function(t,n,r,s){var l=t(function(t,e){c(t,l,n,"_i"),t._i=i(null),t._f=void 0,t._l=void 0,t[d]=0,void 0!=e&&a(e,r,t[s],t)});return o(l.prototype,{clear:function(){for(var t=this,n=t._i,r=t._f;r;r=r.n)r.r=!0,r.p&&(r.p=r.p.n=void 0),delete n[r.i];t._f=t._l=void 0,t[d]=0},delete:function(t){var n=this,r=y(n,t);if(r){var e=r.n,i=r.p;delete n._i[r.i],r.r=!0,i&&(i.n=e),e&&(e.p=i),n._f==r&&(n._f=e),n._l==r&&(n._l=i),n[d]--}return!!r},forEach:function(t){c(this,l,"forEach");for(var n,r=u(t,arguments.length>1?arguments[1]:void 0,3);n=n?n.n:this._f;)for(r(n.v,n.k,this);n&&n.r;)n=n.p},has:function(t){return!!y(this,t)}}),v&&e(l.prototype,"size",{get:function(){return f(this[d])}}),l},def:function(t,n,r){var e,i,o=y(t,n);return o?o.v=r:(t._l=o={i:i=p(n,!0),k:n,v:r,p:e=t._l,n:void 0,r:!1},t._f||(t._f=o),e&&(e.n=o),t[d]++,"F"!==i&&(t._i[i]=o)),t},getEntry:y,setStrong:function(t,n,r){s(t,n,function(t,n){this._t=t,this._k=n,this._l=void 0},function(){for(var t=this,n=t._k,r=t._l;r&&r.r;)r=r.p;return t._t&&(t._l=r=r?r.n:t._t._f)?"keys"==n?l(0,r.k):"values"==n?l(0,r.v):l(0,[r.k,r.v]):(t._t=void 0,l(1))},r?"entries":"values",!r,!0),h(n)}}},function(t,n,r){var e=r(114),i=r(161);t.exports=function(t){return function(){if(e(this)!=t)throw TypeError(t+"#toJSON isn't generic");return i(this)}}},function(t,n,r){"use strict";var e=r(73),i=r(65).getWeak,o=r(2),u=r(6),c=r(68),f=r(79),a=r(48),s=r(24),l=a(5),h=a(6),v=0,p=function(t){return t._l||(t._l=new d)},d=function(){this.a=[]},y=function(t,n){return l(t.a,function(t){return t[0]===n})};d.prototype={get:function(t){var n=y(this,t);if(n)return n[1]},has:function(t){return!!y(this,t)},set:function(t,n){var r=y(this,t);r?r[1]=n:this.a.push([t,n])},delete:function(t){var n=h(this.a,function(n){return n[0]===t});return~n&&this.a.splice(n,1),!!~n}},t.exports={getConstructor:function(t,n,r,o){var a=t(function(t,e){c(t,a,n,"_i"),t._i=v++,t._l=void 0,void 0!=e&&f(e,r,t[o],t)});return e(a.prototype,{delete:function(t){if(!u(t))return!1;var n=i(t);return!0===n?p(this).delete(t):n&&s(n,this._i)&&delete n[this._i]},has:function(t){if(!u(t))return!1;var n=i(t);return!0===n?p(this).has(t):n&&s(n,this._i)}}),a},def:function(t,n,r){var e=i(o(n),!0);return!0===e?p(t).set(n,r):e[t._i]=r,t},ufstore:p}},function(t,n,r){t.exports=!r(10)&&!r(4)(function(){return 7!=Object.defineProperty(r(132)("div"),"a",{get:function(){return 7}}).a})},function(t,n,r){var e=r(6),i=Math.floor;t.exports=function(t){return!e(t)&&isFinite(t)&&i(t)===t}},function(t,n,r){var e=r(2);t.exports=function(t,n,r,i){try{return i?n(e(r)[0],r[1]):n(r)}catch(n){var o=t.return;throw void 0!==o&&e(o.call(t)),n}}},function(t,n){t.exports=function(t,n){return{value:n,done:!!t}}},function(t,n){t.exports=Math.log1p||function(t){return(t=+t)>-1e-8&&t<1e-8?t-t*t/2:Math.log(1+t)}},function(t,n,r){"use strict";var e=r(72),i=r(125),o=r(116),u=r(17),c=r(115),f=Object.assign;t.exports=!f||r(4)(function(){var t={},n={},r=Symbol(),e="abcdefghijklmnopqrst";return t[r]=7,e.split("").forEach(function(t){n[t]=t}),7!=f({},t)[r]||Object.keys(f({},n)).join("")!=e})?function(t,n){for(var r=u(t),f=arguments.length,a=1,s=i.f,l=o.f;f>a;)for(var h,v=c(arguments[a++]),p=s?e(v).concat(s(v)):e(v),d=p.length,y=0;d>y;)l.call(v,h=p[y++])&&(r[h]=v[h]);return r}:f},function(t,n,r){var e=r(11),i=r(2),o=r(72);t.exports=r(10)?Object.defineProperties:function(t,n){i(t);for(var r,u=o(n),c=u.length,f=0;c>f;)e.f(t,r=u[f++],n[r]);return t}},function(t,n,r){var e=r(30),i=r(71).f,o={}.toString,u="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],c=function(t){try{return i(t)}catch(t){return u.slice()}};t.exports.f=function(t){return u&&"[object Window]"==o.call(t)?c(t):i(e(t))}},function(t,n,r){var e=r(24),i=r(30),o=r(117)(!1),u=r(145)("IE_PROTO");t.exports=function(t,n){var r,c=i(t),f=0,a=[];for(r in c)r!=u&&e(c,r)&&a.push(r);for(;n.length>f;)e(c,r=n[f++])&&(~o(a,r)||a.push(r));return a}},function(t,n,r){var e=r(72),i=r(30),o=r(116).f;t.exports=function(t){return function(n){for(var r,u=i(n),c=e(u),f=c.length,a=0,s=[];f>a;)o.call(u,r=c[a++])&&s.push(t?[r,u[r]]:u[r]);return s}}},function(t,n,r){var e=r(71),i=r(125),o=r(2),u=r(3).Reflect;t.exports=u&&u.ownKeys||function(t){var n=e.f(o(t)),r=i.f;return r?n.concat(r(t)):n}},function(t,n,r){var e=r(3).parseFloat,i=r(82).trim;t.exports=1/e(r(150)+"-0")!=-1/0?function(t){var n=i(String(t),3),r=e(n);return 0===r&&"-"==n.charAt(0)?-0:r}:e},function(t,n,r){var e=r(3).parseInt,i=r(82).trim,o=r(150),u=/^[\-+]?0[xX]/;t.exports=8!==e(o+"08")||22!==e(o+"0x16")?function(t,n){var r=i(String(t),3);return e(r,n>>>0||(u.test(r)?16:10))}:e},function(t,n){t.exports=Object.is||function(t,n){return t===n?0!==t||1/t==1/n:t!=t&&n!=n}},function(t,n,r){var e=r(16),i=r(149),o=r(46);t.exports=function(t,n,r,u){var c=String(o(t)),f=c.length,a=void 0===r?" ":String(r),s=e(n);if(s<=f||""==a)return c;var l=s-f,h=i.call(a,Math.ceil(l/a.length));return h.length>l&&(h=h.slice(0,l)),u?h+c:c+h}},function(t,n,r){n.f=r(7)},function(t,n,r){"use strict";var e=r(164);t.exports=r(118)("Map",function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{get:function(t){var n=e.getEntry(this,t);return n&&n.v},set:function(t,n){return e.def(this,0===t?0:t,n)}},e,!0)},function(t,n,r){r(10)&&"g"!=/./g.flags&&r(11).f(RegExp.prototype,"flags",{configurable:!0,get:r(120)})},function(t,n,r){"use strict";var e=r(164);t.exports=r(118)("Set",function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{add:function(t){return e.def(this,t=0===t?0:t,t)}},e)},function(t,n,r){"use strict";var e,i=r(48)(0),o=r(28),u=r(65),c=r(172),f=r(166),a=r(6),s=u.getWeak,l=Object.isExtensible,h=f.ufstore,v={},p=function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},d={get:function(t){if(a(t)){var n=s(t);return!0===n?h(this).get(t):n?n[this._i]:void 0}},set:function(t,n){return f.def(this,t,n)}},y=t.exports=r(118)("WeakMap",p,d,f,!0,!0);7!=(new y).set((Object.freeze||Object)(v),7).get(v)&&(e=f.getConstructor(p),c(e.prototype,d),u.NEED=!0,i(["delete","has","get","set"],function(t){var n=y.prototype,r=n[t];o(n,t,function(n,i){if(a(n)&&!l(n)){this._f||(this._f=new e);var o=this._f[t](n,i);return"set"==t?this:o}return r.call(this,n,i)})}))},,,,function(t,n){"use strict";function r(){var t=document.querySelector("#page-nav");if(t&&!document.querySelector("#page-nav .extend.prev")&&(t.innerHTML='<a class="extend prev disabled" rel="prev">&laquo; Prev</a>'+t.innerHTML),t&&!document.querySelector("#page-nav .extend.next")&&(t.innerHTML=t.innerHTML+'<a class="extend next disabled" rel="next">Next &raquo;</a>'),yiliaConfig&&yiliaConfig.open_in_new){document.querySelectorAll(".article-entry a:not(.article-more-a)").forEach(function(t){var n=t.getAttribute("target");n&&""!==n||t.setAttribute("target","_blank")})}if(yiliaConfig&&yiliaConfig.toc_hide_index){document.querySelectorAll(".toc-number").forEach(function(t){t.style.display="none"})}var n=document.querySelector("#js-aboutme");n&&0!==n.length&&(n.innerHTML=n.innerText)}t.exports={init:r}},function(t,n,r){"use strict";function e(t){return t&&t.__esModule?t:{default:t}}function i(t,n){var r=/\/|index.html/g;return t.replace(r,"")===n.replace(r,"")}function o(){for(var t=document.querySelectorAll(".js-header-menu li a"),n=window.location.pathname,r=0,e=t.length;r<e;r++){var o=t[r];i(n,o.getAttribute("href"))&&(0,h.default)(o,"active")}}function u(t){for(var n=t.offsetLeft,r=t.offsetParent;null!==r;)n+=r.offsetLeft,r=r.offsetParent;return n}function c(t){for(var n=t.offsetTop,r=t.offsetParent;null!==r;)n+=r.offsetTop,r=r.offsetParent;return n}function f(t,n,r,e,i){var o=u(t),f=c(t)-n;if(f-r<=i){var a=t.$newDom;a||(a=t.cloneNode(!0),(0,d.default)(t,a),t.$newDom=a,a.style.position="fixed",a.style.top=(r||f)+"px",a.style.left=o+"px",a.style.zIndex=e||2,a.style.width="100%",a.style.color="#fff"),a.style.visibility="visible",t.style.visibility="hidden"}else{t.style.visibility="visible";var s=t.$newDom;s&&(s.style.visibility="hidden")}}function a(){var t=document.querySelector(".js-overlay"),n=document.querySelector(".js-header-menu");f(t,document.body.scrollTop,-63,2,0),f(n,document.body.scrollTop,1,3,0)}function s(){document.querySelector("#container").addEventListener("scroll",function(t){a()}),window.addEventListener("scroll",function(t){a()}),a()}var l=r(156),h=e(l),v=r(157),p=(e(v),r(382)),d=e(p),y=r(128),g=e(y),b=r(190),m=e(b),x=r(129);(function(){g.default.versions.mobile&&window.screen.width<800&&(o(),s())})(),(0,x.addLoadEvent)(function(){m.default.init()}),t.exports={}},,,,function(t,n,r){(function(t){"use strict";function n(t,n,r){t[n]||Object[e](t,n,{writable:!0,configurable:!0,value:r})}if(r(381),r(391),r(198),t._babelPolyfill)throw new Error("only one instance of babel-polyfill is allowed");t._babelPolyfill=!0;var e="defineProperty";n(String.prototype,"padLeft","".padStart),n(String.prototype,"padRight","".padEnd),"pop,reverse,shift,keys,values,entries,indexOf,every,some,forEach,map,filter,find,findIndex,includes,join,slice,concat,push,splice,unshift,sort,lastIndexOf,reduce,reduceRight,copyWithin,fill".split(",").forEach(function(t){[][t]&&n(Array,t,Function.call.bind([][t]))})}).call(n,function(){return this}())},,,function(t,n,r){r(210),t.exports=r(52).RegExp.escape},,,,function(t,n,r){var e=r(6),i=r(138),o=r(7)("species");t.exports=function(t){var n;return i(t)&&(n=t.constructor,"function"!=typeof n||n!==Array&&!i(n.prototype)||(n=void 0),e(n)&&null===(n=n[o])&&(n=void 0)),void 0===n?Array:n}},function(t,n,r){var e=r(202);t.exports=function(t,n){return new(e(t))(n)}},function(t,n,r){"use strict";var e=r(2),i=r(50),o="number";t.exports=function(t){if("string"!==t&&t!==o&&"default"!==t)throw TypeError("Incorrect hint");return i(e(this),t!=o)}},function(t,n,r){var e=r(72),i=r(125),o=r(116);t.exports=function(t){var n=e(t),r=i.f;if(r)for(var u,c=r(t),f=o.f,a=0;c.length>a;)f.call(t,u=c[a++])&&n.push(u);return n}},function(t,n,r){var e=r(72),i=r(30);t.exports=function(t,n){for(var r,o=i(t),u=e(o),c=u.length,f=0;c>f;)if(o[r=u[f++]]===n)return r}},function(t,n,r){"use strict";var e=r(208),i=r(121),o=r(26);t.exports=function(){for(var t=o(this),n=arguments.length,r=Array(n),u=0,c=e._,f=!1;n>u;)(r[u]=arguments[u++])===c&&(f=!0);return function(){var e,o=this,u=arguments.length,a=0,s=0;if(!f&&!u)return i(t,r,o);if(e=r.slice(),f)for(;n>a;a++)e[a]===c&&(e[a]=arguments[s++]);for(;u>s;)e.push(arguments[s++]);return i(t,e,o)}}},function(t,n,r){t.exports=r(3)},function(t,n){t.exports=function(t,n){var r=n===Object(n)?function(t){return n[t]}:n;return function(n){return String(n).replace(t,r)}}},function(t,n,r){var e=r(1),i=r(209)(/[\\^$*+?.()|[\]{}]/g,"\\$&");e(e.S,"RegExp",{escape:function(t){return i(t)}})},function(t,n,r){var e=r(1);e(e.P,"Array",{copyWithin:r(160)}),r(78)("copyWithin")},function(t,n,r){"use strict";var e=r(1),i=r(48)(4);e(e.P+e.F*!r(47)([].every,!0),"Array",{every:function(t){return i(this,t,arguments[1])}})},function(t,n,r){var e=r(1);e(e.P,"Array",{fill:r(130)}),r(78)("fill")},function(t,n,r){"use strict";var e=r(1),i=r(48)(2);e(e.P+e.F*!r(47)([].filter,!0),"Array",{filter:function(t){return i(this,t,arguments[1])}})},function(t,n,r){"use strict";var e=r(1),i=r(48)(6),o="findIndex",u=!0;o in[]&&Array(1)[o](function(){u=!1}),e(e.P+e.F*u,"Array",{findIndex:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}}),r(78)(o)},function(t,n,r){"use strict";var e=r(1),i=r(48)(5),o="find",u=!0;o in[]&&Array(1)[o](function(){u=!1}),e(e.P+e.F*u,"Array",{find:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}}),r(78)(o)},function(t,n,r){"use strict";var e=r(1),i=r(48)(0),o=r(47)([].forEach,!0);e(e.P+e.F*!o,"Array",{forEach:function(t){return i(this,t,arguments[1])}})},function(t,n,r){"use strict";var e=r(53),i=r(1),o=r(17),u=r(169),c=r(137),f=r(16),a=r(131),s=r(154);i(i.S+i.F*!r(123)(function(t){Array.from(t)}),"Array",{from:function(t){var n,r,i,l,h=o(t),v="function"==typeof this?this:Array,p=arguments.length,d=p>1?arguments[1]:void 0,y=void 0!==d,g=0,b=s(h);if(y&&(d=e(d,p>2?arguments[2]:void 0,2)),void 0==b||v==Array&&c(b))for(n=f(h.length),r=new v(n);n>g;g++)a(r,g,y?d(h[g],g):h[g]);else for(l=b.call(h),r=new v;!(i=l.next()).done;g++)a(r,g,y?u(l,d,[i.value,g],!0):i.value);return r.length=g,r}})},function(t,n,r){"use strict";var e=r(1),i=r(117)(!1),o=[].indexOf,u=!!o&&1/[1].indexOf(1,-0)<0;e(e.P+e.F*(u||!r(47)(o)),"Array",{indexOf:function(t){return u?o.apply(this,arguments)||0:i(this,t,arguments[1])}})},function(t,n,r){var e=r(1);e(e.S,"Array",{isArray:r(138)})},function(t,n,r){"use strict";var e=r(1),i=r(30),o=[].join;e(e.P+e.F*(r(115)!=Object||!r(47)(o)),"Array",{join:function(t){return o.call(i(this),void 0===t?",":t)}})},function(t,n,r){"use strict";var e=r(1),i=r(30),o=r(67),u=r(16),c=[].lastIndexOf,f=!!c&&1/[1].lastIndexOf(1,-0)<0;e(e.P+e.F*(f||!r(47)(c)),"Array",{lastIndexOf:function(t){if(f)return c.apply(this,arguments)||0;var n=i(this),r=u(n.length),e=r-1;for(arguments.length>1&&(e=Math.min(e,o(arguments[1]))),e<0&&(e=r+e);e>=0;e--)if(e in n&&n[e]===t)return e||0;return-1}})},function(t,n,r){"use strict";var e=r(1),i=r(48)(1);e(e.P+e.F*!r(47)([].map,!0),"Array",{map:function(t){return i(this,t,arguments[1])}})},function(t,n,r){"use strict";var e=r(1),i=r(131);e(e.S+e.F*r(4)(function(){function t(){}return!(Array.of.call(t)instanceof t)}),"Array",{of:function(){for(var t=0,n=arguments.length,r=new("function"==typeof this?this:Array)(n);n>t;)i(r,t,arguments[t++]);return r.length=n,r}})},function(t,n,r){"use strict";var e=r(1),i=r(162);e(e.P+e.F*!r(47)([].reduceRight,!0),"Array",{reduceRight:function(t){return i(this,t,arguments.length,arguments[1],!0)}})},function(t,n,r){"use strict";var e=r(1),i=r(162);e(e.P+e.F*!r(47)([].reduce,!0),"Array",{reduce:function(t){return i(this,t,arguments.length,arguments[1],!1)}})},function(t,n,r){"use strict";var e=r(1),i=r(135),o=r(45),u=r(75),c=r(16),f=[].slice;e(e.P+e.F*r(4)(function(){i&&f.call(i)}),"Array",{slice:function(t,n){var r=c(this.length),e=o(this);if(n=void 0===n?r:n,"Array"==e)return f.call(this,t,n);for(var i=u(t,r),a=u(n,r),s=c(a-i),l=Array(s),h=0;h<s;h++)l[h]="String"==e?this.charAt(i+h):this[i+h];return l}})},function(t,n,r){"use strict";var e=r(1),i=r(48)(3);e(e.P+e.F*!r(47)([].some,!0),"Array",{some:function(t){return i(this,t,arguments[1])}})},function(t,n,r){"use strict";var e=r(1),i=r(26),o=r(17),u=r(4),c=[].sort,f=[1,2,3];e(e.P+e.F*(u(function(){f.sort(void 0)})||!u(function(){f.sort(null)})||!r(47)(c)),"Array",{sort:function(t){return void 0===t?c.call(o(this)):c.call(o(this),i(t))}})},function(t,n,r){r(74)("Array")},function(t,n,r){var e=r(1);e(e.S,"Date",{now:function(){return(new Date).getTime()}})},function(t,n,r){"use strict";var e=r(1),i=r(4),o=Date.prototype.getTime,u=function(t){return t>9?t:"0"+t};e(e.P+e.F*(i(function(){return"0385-07-25T07:06:39.999Z"!=new Date(-5e13-1).toISOString()})||!i(function(){new Date(NaN).toISOString()})),"Date",{toISOString:function(){
if(!isFinite(o.call(this)))throw RangeError("Invalid time value");var t=this,n=t.getUTCFullYear(),r=t.getUTCMilliseconds(),e=n<0?"-":n>9999?"+":"";return e+("00000"+Math.abs(n)).slice(e?-6:-4)+"-"+u(t.getUTCMonth()+1)+"-"+u(t.getUTCDate())+"T"+u(t.getUTCHours())+":"+u(t.getUTCMinutes())+":"+u(t.getUTCSeconds())+"."+(r>99?r:"0"+u(r))+"Z"}})},function(t,n,r){"use strict";var e=r(1),i=r(17),o=r(50);e(e.P+e.F*r(4)(function(){return null!==new Date(NaN).toJSON()||1!==Date.prototype.toJSON.call({toISOString:function(){return 1}})}),"Date",{toJSON:function(t){var n=i(this),r=o(n);return"number"!=typeof r||isFinite(r)?n.toISOString():null}})},function(t,n,r){var e=r(7)("toPrimitive"),i=Date.prototype;e in i||r(27)(i,e,r(204))},function(t,n,r){var e=Date.prototype,i="Invalid Date",o="toString",u=e[o],c=e.getTime;new Date(NaN)+""!=i&&r(28)(e,o,function(){var t=c.call(this);return t===t?u.call(this):i})},function(t,n,r){var e=r(1);e(e.P,"Function",{bind:r(163)})},function(t,n,r){"use strict";var e=r(6),i=r(32),o=r(7)("hasInstance"),u=Function.prototype;o in u||r(11).f(u,o,{value:function(t){if("function"!=typeof this||!e(t))return!1;if(!e(this.prototype))return t instanceof this;for(;t=i(t);)if(this.prototype===t)return!0;return!1}})},function(t,n,r){var e=r(11).f,i=r(66),o=r(24),u=Function.prototype,c="name",f=Object.isExtensible||function(){return!0};c in u||r(10)&&e(u,c,{configurable:!0,get:function(){try{var t=this,n=(""+t).match(/^\s*function ([^ (]*)/)[1];return o(t,c)||!f(t)||e(t,c,i(5,n)),n}catch(t){return""}}})},function(t,n,r){var e=r(1),i=r(171),o=Math.sqrt,u=Math.acosh;e(e.S+e.F*!(u&&710==Math.floor(u(Number.MAX_VALUE))&&u(1/0)==1/0),"Math",{acosh:function(t){return(t=+t)<1?NaN:t>94906265.62425156?Math.log(t)+Math.LN2:i(t-1+o(t-1)*o(t+1))}})},function(t,n,r){function e(t){return isFinite(t=+t)&&0!=t?t<0?-e(-t):Math.log(t+Math.sqrt(t*t+1)):t}var i=r(1),o=Math.asinh;i(i.S+i.F*!(o&&1/o(0)>0),"Math",{asinh:e})},function(t,n,r){var e=r(1),i=Math.atanh;e(e.S+e.F*!(i&&1/i(-0)<0),"Math",{atanh:function(t){return 0==(t=+t)?t:Math.log((1+t)/(1-t))/2}})},function(t,n,r){var e=r(1),i=r(142);e(e.S,"Math",{cbrt:function(t){return i(t=+t)*Math.pow(Math.abs(t),1/3)}})},function(t,n,r){var e=r(1);e(e.S,"Math",{clz32:function(t){return(t>>>=0)?31-Math.floor(Math.log(t+.5)*Math.LOG2E):32}})},function(t,n,r){var e=r(1),i=Math.exp;e(e.S,"Math",{cosh:function(t){return(i(t=+t)+i(-t))/2}})},function(t,n,r){var e=r(1),i=r(141);e(e.S+e.F*(i!=Math.expm1),"Math",{expm1:i})},function(t,n,r){var e=r(1),i=r(142),o=Math.pow,u=o(2,-52),c=o(2,-23),f=o(2,127)*(2-c),a=o(2,-126),s=function(t){return t+1/u-1/u};e(e.S,"Math",{fround:function(t){var n,r,e=Math.abs(t),o=i(t);return e<a?o*s(e/a/c)*a*c:(n=(1+c/u)*e,r=n-(n-e),r>f||r!=r?o*(1/0):o*r)}})},function(t,n,r){var e=r(1),i=Math.abs;e(e.S,"Math",{hypot:function(t,n){for(var r,e,o=0,u=0,c=arguments.length,f=0;u<c;)r=i(arguments[u++]),f<r?(e=f/r,o=o*e*e+1,f=r):r>0?(e=r/f,o+=e*e):o+=r;return f===1/0?1/0:f*Math.sqrt(o)}})},function(t,n,r){var e=r(1),i=Math.imul;e(e.S+e.F*r(4)(function(){return-5!=i(4294967295,5)||2!=i.length}),"Math",{imul:function(t,n){var r=65535,e=+t,i=+n,o=r&e,u=r&i;return 0|o*u+((r&e>>>16)*u+o*(r&i>>>16)<<16>>>0)}})},function(t,n,r){var e=r(1);e(e.S,"Math",{log10:function(t){return Math.log(t)/Math.LN10}})},function(t,n,r){var e=r(1);e(e.S,"Math",{log1p:r(171)})},function(t,n,r){var e=r(1);e(e.S,"Math",{log2:function(t){return Math.log(t)/Math.LN2}})},function(t,n,r){var e=r(1);e(e.S,"Math",{sign:r(142)})},function(t,n,r){var e=r(1),i=r(141),o=Math.exp;e(e.S+e.F*r(4)(function(){return-2e-17!=!Math.sinh(-2e-17)}),"Math",{sinh:function(t){return Math.abs(t=+t)<1?(i(t)-i(-t))/2:(o(t-1)-o(-t-1))*(Math.E/2)}})},function(t,n,r){var e=r(1),i=r(141),o=Math.exp;e(e.S,"Math",{tanh:function(t){var n=i(t=+t),r=i(-t);return n==1/0?1:r==1/0?-1:(n-r)/(o(t)+o(-t))}})},function(t,n,r){var e=r(1);e(e.S,"Math",{trunc:function(t){return(t>0?Math.floor:Math.ceil)(t)}})},function(t,n,r){"use strict";var e=r(3),i=r(24),o=r(45),u=r(136),c=r(50),f=r(4),a=r(71).f,s=r(31).f,l=r(11).f,h=r(82).trim,v="Number",p=e[v],d=p,y=p.prototype,g=o(r(70)(y))==v,b="trim"in String.prototype,m=function(t){var n=c(t,!1);if("string"==typeof n&&n.length>2){n=b?n.trim():h(n,3);var r,e,i,o=n.charCodeAt(0);if(43===o||45===o){if(88===(r=n.charCodeAt(2))||120===r)return NaN}else if(48===o){switch(n.charCodeAt(1)){case 66:case 98:e=2,i=49;break;case 79:case 111:e=8,i=55;break;default:return+n}for(var u,f=n.slice(2),a=0,s=f.length;a<s;a++)if((u=f.charCodeAt(a))<48||u>i)return NaN;return parseInt(f,e)}}return+n};if(!p(" 0o1")||!p("0b1")||p("+0x1")){p=function(t){var n=arguments.length<1?0:t,r=this;return r instanceof p&&(g?f(function(){y.valueOf.call(r)}):o(r)!=v)?u(new d(m(n)),r,p):m(n)};for(var x,w=r(10)?a(d):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger".split(","),S=0;w.length>S;S++)i(d,x=w[S])&&!i(p,x)&&l(p,x,s(d,x));p.prototype=y,y.constructor=p,r(28)(e,v,p)}},function(t,n,r){var e=r(1);e(e.S,"Number",{EPSILON:Math.pow(2,-52)})},function(t,n,r){var e=r(1),i=r(3).isFinite;e(e.S,"Number",{isFinite:function(t){return"number"==typeof t&&i(t)}})},function(t,n,r){var e=r(1);e(e.S,"Number",{isInteger:r(168)})},function(t,n,r){var e=r(1);e(e.S,"Number",{isNaN:function(t){return t!=t}})},function(t,n,r){var e=r(1),i=r(168),o=Math.abs;e(e.S,"Number",{isSafeInteger:function(t){return i(t)&&o(t)<=9007199254740991}})},function(t,n,r){var e=r(1);e(e.S,"Number",{MAX_SAFE_INTEGER:9007199254740991})},function(t,n,r){var e=r(1);e(e.S,"Number",{MIN_SAFE_INTEGER:-9007199254740991})},function(t,n,r){var e=r(1),i=r(178);e(e.S+e.F*(Number.parseFloat!=i),"Number",{parseFloat:i})},function(t,n,r){var e=r(1),i=r(179);e(e.S+e.F*(Number.parseInt!=i),"Number",{parseInt:i})},function(t,n,r){"use strict";var e=r(1),i=r(67),o=r(159),u=r(149),c=1..toFixed,f=Math.floor,a=[0,0,0,0,0,0],s="Number.toFixed: incorrect invocation!",l="0",h=function(t,n){for(var r=-1,e=n;++r<6;)e+=t*a[r],a[r]=e%1e7,e=f(e/1e7)},v=function(t){for(var n=6,r=0;--n>=0;)r+=a[n],a[n]=f(r/t),r=r%t*1e7},p=function(){for(var t=6,n="";--t>=0;)if(""!==n||0===t||0!==a[t]){var r=String(a[t]);n=""===n?r:n+u.call(l,7-r.length)+r}return n},d=function(t,n,r){return 0===n?r:n%2==1?d(t,n-1,r*t):d(t*t,n/2,r)},y=function(t){for(var n=0,r=t;r>=4096;)n+=12,r/=4096;for(;r>=2;)n+=1,r/=2;return n};e(e.P+e.F*(!!c&&("0.000"!==8e-5.toFixed(3)||"1"!==.9.toFixed(0)||"1.25"!==1.255.toFixed(2)||"1000000000000000128"!==(0xde0b6b3a7640080).toFixed(0))||!r(4)(function(){c.call({})})),"Number",{toFixed:function(t){var n,r,e,c,f=o(this,s),a=i(t),g="",b=l;if(a<0||a>20)throw RangeError(s);if(f!=f)return"NaN";if(f<=-1e21||f>=1e21)return String(f);if(f<0&&(g="-",f=-f),f>1e-21)if(n=y(f*d(2,69,1))-69,r=n<0?f*d(2,-n,1):f/d(2,n,1),r*=4503599627370496,(n=52-n)>0){for(h(0,r),e=a;e>=7;)h(1e7,0),e-=7;for(h(d(10,e,1),0),e=n-1;e>=23;)v(1<<23),e-=23;v(1<<e),h(1,1),v(2),b=p()}else h(0,r),h(1<<-n,0),b=p()+u.call(l,a);return a>0?(c=b.length,b=g+(c<=a?"0."+u.call(l,a-c)+b:b.slice(0,c-a)+"."+b.slice(c-a))):b=g+b,b}})},function(t,n,r){"use strict";var e=r(1),i=r(4),o=r(159),u=1..toPrecision;e(e.P+e.F*(i(function(){return"1"!==u.call(1,void 0)})||!i(function(){u.call({})})),"Number",{toPrecision:function(t){var n=o(this,"Number#toPrecision: incorrect invocation!");return void 0===t?u.call(n):u.call(n,t)}})},function(t,n,r){var e=r(1);e(e.S+e.F,"Object",{assign:r(172)})},function(t,n,r){var e=r(1);e(e.S,"Object",{create:r(70)})},function(t,n,r){var e=r(1);e(e.S+e.F*!r(10),"Object",{defineProperties:r(173)})},function(t,n,r){var e=r(1);e(e.S+e.F*!r(10),"Object",{defineProperty:r(11).f})},function(t,n,r){var e=r(6),i=r(65).onFreeze;r(49)("freeze",function(t){return function(n){return t&&e(n)?t(i(n)):n}})},function(t,n,r){var e=r(30),i=r(31).f;r(49)("getOwnPropertyDescriptor",function(){return function(t,n){return i(e(t),n)}})},function(t,n,r){r(49)("getOwnPropertyNames",function(){return r(174).f})},function(t,n,r){var e=r(17),i=r(32);r(49)("getPrototypeOf",function(){return function(t){return i(e(t))}})},function(t,n,r){var e=r(6);r(49)("isExtensible",function(t){return function(n){return!!e(n)&&(!t||t(n))}})},function(t,n,r){var e=r(6);r(49)("isFrozen",function(t){return function(n){return!e(n)||!!t&&t(n)}})},function(t,n,r){var e=r(6);r(49)("isSealed",function(t){return function(n){return!e(n)||!!t&&t(n)}})},function(t,n,r){var e=r(1);e(e.S,"Object",{is:r(180)})},function(t,n,r){var e=r(17),i=r(72);r(49)("keys",function(){return function(t){return i(e(t))}})},function(t,n,r){var e=r(6),i=r(65).onFreeze;r(49)("preventExtensions",function(t){return function(n){return t&&e(n)?t(i(n)):n}})},function(t,n,r){var e=r(6),i=r(65).onFreeze;r(49)("seal",function(t){return function(n){return t&&e(n)?t(i(n)):n}})},function(t,n,r){var e=r(1);e(e.S,"Object",{setPrototypeOf:r(144).set})},function(t,n,r){"use strict";var e=r(114),i={};i[r(7)("toStringTag")]="z",i+""!="[object z]"&&r(28)(Object.prototype,"toString",function(){return"[object "+e(this)+"]"},!0)},function(t,n,r){var e=r(1),i=r(178);e(e.G+e.F*(parseFloat!=i),{parseFloat:i})},function(t,n,r){var e=r(1),i=r(179);e(e.G+e.F*(parseInt!=i),{parseInt:i})},function(t,n,r){"use strict";var e,i,o,u=r(69),c=r(3),f=r(53),a=r(114),s=r(1),l=r(6),h=r(26),v=r(68),p=r(79),d=r(146),y=r(151).set,g=r(143)(),b="Promise",m=c.TypeError,x=c.process,w=c[b],x=c.process,S="process"==a(x),_=function(){},O=!!function(){try{var t=w.resolve(1),n=(t.constructor={})[r(7)("species")]=function(t){t(_,_)};return(S||"function"==typeof PromiseRejectionEvent)&&t.then(_)instanceof n}catch(t){}}(),E=function(t,n){return t===n||t===w&&n===o},P=function(t){var n;return!(!l(t)||"function"!=typeof(n=t.then))&&n},j=function(t){return E(w,t)?new F(t):new i(t)},F=i=function(t){var n,r;this.promise=new t(function(t,e){if(void 0!==n||void 0!==r)throw m("Bad Promise constructor");n=t,r=e}),this.resolve=h(n),this.reject=h(r)},M=function(t){try{t()}catch(t){return{error:t}}},A=function(t,n){if(!t._n){t._n=!0;var r=t._c;g(function(){for(var e=t._v,i=1==t._s,o=0;r.length>o;)!function(n){var r,o,u=i?n.ok:n.fail,c=n.resolve,f=n.reject,a=n.domain;try{u?(i||(2==t._h&&I(t),t._h=1),!0===u?r=e:(a&&a.enter(),r=u(e),a&&a.exit()),r===n.promise?f(m("Promise-chain cycle")):(o=P(r))?o.call(r,c,f):c(r)):f(e)}catch(t){f(t)}}(r[o++]);t._c=[],t._n=!1,n&&!t._h&&N(t)})}},N=function(t){y.call(c,function(){var n,r,e,i=t._v;if(T(t)&&(n=M(function(){S?x.emit("unhandledRejection",i,t):(r=c.onunhandledrejection)?r({promise:t,reason:i}):(e=c.console)&&e.error&&e.error("Unhandled promise rejection",i)}),t._h=S||T(t)?2:1),t._a=void 0,n)throw n.error})},T=function(t){if(1==t._h)return!1;for(var n,r=t._a||t._c,e=0;r.length>e;)if(n=r[e++],n.fail||!T(n.promise))return!1;return!0},I=function(t){y.call(c,function(){var n;S?x.emit("rejectionHandled",t):(n=c.onrejectionhandled)&&n({promise:t,reason:t._v})})},k=function(t){var n=this;n._d||(n._d=!0,n=n._w||n,n._v=t,n._s=2,n._a||(n._a=n._c.slice()),A(n,!0))},L=function(t){var n,r=this;if(!r._d){r._d=!0,r=r._w||r;try{if(r===t)throw m("Promise can't be resolved itself");(n=P(t))?g(function(){var e={_w:r,_d:!1};try{n.call(t,f(L,e,1),f(k,e,1))}catch(t){k.call(e,t)}}):(r._v=t,r._s=1,A(r,!1))}catch(t){k.call({_w:r,_d:!1},t)}}};O||(w=function(t){v(this,w,b,"_h"),h(t),e.call(this);try{t(f(L,this,1),f(k,this,1))}catch(t){k.call(this,t)}},e=function(t){this._c=[],this._a=void 0,this._s=0,this._d=!1,this._v=void 0,this._h=0,this._n=!1},e.prototype=r(73)(w.prototype,{then:function(t,n){var r=j(d(this,w));return r.ok="function"!=typeof t||t,r.fail="function"==typeof n&&n,r.domain=S?x.domain:void 0,this._c.push(r),this._a&&this._a.push(r),this._s&&A(this,!1),r.promise},catch:function(t){return this.then(void 0,t)}}),F=function(){var t=new e;this.promise=t,this.resolve=f(L,t,1),this.reject=f(k,t,1)}),s(s.G+s.W+s.F*!O,{Promise:w}),r(81)(w,b),r(74)(b),o=r(52)[b],s(s.S+s.F*!O,b,{reject:function(t){var n=j(this);return(0,n.reject)(t),n.promise}}),s(s.S+s.F*(u||!O),b,{resolve:function(t){if(t instanceof w&&E(t.constructor,this))return t;var n=j(this);return(0,n.resolve)(t),n.promise}}),s(s.S+s.F*!(O&&r(123)(function(t){w.all(t).catch(_)})),b,{all:function(t){var n=this,r=j(n),e=r.resolve,i=r.reject,o=M(function(){var r=[],o=0,u=1;p(t,!1,function(t){var c=o++,f=!1;r.push(void 0),u++,n.resolve(t).then(function(t){f||(f=!0,r[c]=t,--u||e(r))},i)}),--u||e(r)});return o&&i(o.error),r.promise},race:function(t){var n=this,r=j(n),e=r.reject,i=M(function(){p(t,!1,function(t){n.resolve(t).then(r.resolve,e)})});return i&&e(i.error),r.promise}})},function(t,n,r){var e=r(1),i=r(26),o=r(2),u=(r(3).Reflect||{}).apply,c=Function.apply;e(e.S+e.F*!r(4)(function(){u(function(){})}),"Reflect",{apply:function(t,n,r){var e=i(t),f=o(r);return u?u(e,n,f):c.call(e,n,f)}})},function(t,n,r){var e=r(1),i=r(70),o=r(26),u=r(2),c=r(6),f=r(4),a=r(163),s=(r(3).Reflect||{}).construct,l=f(function(){function t(){}return!(s(function(){},[],t)instanceof t)}),h=!f(function(){s(function(){})});e(e.S+e.F*(l||h),"Reflect",{construct:function(t,n){o(t),u(n);var r=arguments.length<3?t:o(arguments[2]);if(h&&!l)return s(t,n,r);if(t==r){switch(n.length){case 0:return new t;case 1:return new t(n[0]);case 2:return new t(n[0],n[1]);case 3:return new t(n[0],n[1],n[2]);case 4:return new t(n[0],n[1],n[2],n[3])}var e=[null];return e.push.apply(e,n),new(a.apply(t,e))}var f=r.prototype,v=i(c(f)?f:Object.prototype),p=Function.apply.call(t,v,n);return c(p)?p:v}})},function(t,n,r){var e=r(11),i=r(1),o=r(2),u=r(50);i(i.S+i.F*r(4)(function(){Reflect.defineProperty(e.f({},1,{value:1}),1,{value:2})}),"Reflect",{defineProperty:function(t,n,r){o(t),n=u(n,!0),o(r);try{return e.f(t,n,r),!0}catch(t){return!1}}})},function(t,n,r){var e=r(1),i=r(31).f,o=r(2);e(e.S,"Reflect",{deleteProperty:function(t,n){var r=i(o(t),n);return!(r&&!r.configurable)&&delete t[n]}})},function(t,n,r){"use strict";var e=r(1),i=r(2),o=function(t){this._t=i(t),this._i=0;var n,r=this._k=[];for(n in t)r.push(n)};r(139)(o,"Object",function(){var t,n=this,r=n._k;do{if(n._i>=r.length)return{value:void 0,done:!0}}while(!((t=r[n._i++])in n._t));return{value:t,done:!1}}),e(e.S,"Reflect",{enumerate:function(t){return new o(t)}})},function(t,n,r){var e=r(31),i=r(1),o=r(2);i(i.S,"Reflect",{getOwnPropertyDescriptor:function(t,n){return e.f(o(t),n)}})},function(t,n,r){var e=r(1),i=r(32),o=r(2);e(e.S,"Reflect",{getPrototypeOf:function(t){return i(o(t))}})},function(t,n,r){function e(t,n){var r,c,s=arguments.length<3?t:arguments[2];return a(t)===s?t[n]:(r=i.f(t,n))?u(r,"value")?r.value:void 0!==r.get?r.get.call(s):void 0:f(c=o(t))?e(c,n,s):void 0}var i=r(31),o=r(32),u=r(24),c=r(1),f=r(6),a=r(2);c(c.S,"Reflect",{get:e})},function(t,n,r){var e=r(1);e(e.S,"Reflect",{has:function(t,n){return n in t}})},function(t,n,r){var e=r(1),i=r(2),o=Object.isExtensible;e(e.S,"Reflect",{isExtensible:function(t){return i(t),!o||o(t)}})},function(t,n,r){var e=r(1);e(e.S,"Reflect",{ownKeys:r(177)})},function(t,n,r){var e=r(1),i=r(2),o=Object.preventExtensions;e(e.S,"Reflect",{preventExtensions:function(t){i(t);try{return o&&o(t),!0}catch(t){return!1}}})},function(t,n,r){var e=r(1),i=r(144);i&&e(e.S,"Reflect",{setPrototypeOf:function(t,n){i.check(t,n);try{return i.set(t,n),!0}catch(t){return!1}}})},function(t,n,r){function e(t,n,r){var f,h,v=arguments.length<4?t:arguments[3],p=o.f(s(t),n);if(!p){if(l(h=u(t)))return e(h,n,r,v);p=a(0)}return c(p,"value")?!(!1===p.writable||!l(v)||(f=o.f(v,n)||a(0),f.value=r,i.f(v,n,f),0)):void 0!==p.set&&(p.set.call(v,r),!0)}var i=r(11),o=r(31),u=r(32),c=r(24),f=r(1),a=r(66),s=r(2),l=r(6);f(f.S,"Reflect",{set:e})},function(t,n,r){var e=r(3),i=r(136),o=r(11).f,u=r(71).f,c=r(122),f=r(120),a=e.RegExp,s=a,l=a.prototype,h=/a/g,v=/a/g,p=new a(h)!==h;if(r(10)&&(!p||r(4)(function(){return v[r(7)("match")]=!1,a(h)!=h||a(v)==v||"/a/i"!=a(h,"i")}))){a=function(t,n){var r=this instanceof a,e=c(t),o=void 0===n;return!r&&e&&t.constructor===a&&o?t:i(p?new s(e&&!o?t.source:t,n):s((e=t instanceof a)?t.source:t,e&&o?f.call(t):n),r?this:l,a)};for(var d=u(s),y=0;d.length>y;)!function(t){t in a||o(a,t,{configurable:!0,get:function(){return s[t]},set:function(n){s[t]=n}})}(d[y++]);l.constructor=a,a.prototype=l,r(28)(e,"RegExp",a)}r(74)("RegExp")},function(t,n,r){r(119)("match",1,function(t,n,r){return[function(r){"use strict";var e=t(this),i=void 0==r?void 0:r[n];return void 0!==i?i.call(r,e):new RegExp(r)[n](String(e))},r]})},function(t,n,r){r(119)("replace",2,function(t,n,r){return[function(e,i){"use strict";var o=t(this),u=void 0==e?void 0:e[n];return void 0!==u?u.call(e,o,i):r.call(String(o),e,i)},r]})},function(t,n,r){r(119)("search",1,function(t,n,r){return[function(r){"use strict";var e=t(this),i=void 0==r?void 0:r[n];return void 0!==i?i.call(r,e):new RegExp(r)[n](String(e))},r]})},function(t,n,r){r(119)("split",2,function(t,n,e){"use strict";var i=r(122),o=e,u=[].push,c="split",f="length",a="lastIndex";if("c"=="abbc"[c](/(b)*/)[1]||4!="test"[c](/(?:)/,-1)[f]||2!="ab"[c](/(?:ab)*/)[f]||4!="."[c](/(.?)(.?)/)[f]||"."[c](/()()/)[f]>1||""[c](/.?/)[f]){var s=void 0===/()??/.exec("")[1];e=function(t,n){var r=String(this);if(void 0===t&&0===n)return[];if(!i(t))return o.call(r,t,n);var e,c,l,h,v,p=[],d=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),y=0,g=void 0===n?4294967295:n>>>0,b=new RegExp(t.source,d+"g");for(s||(e=new RegExp("^"+b.source+"$(?!\\s)",d));(c=b.exec(r))&&!((l=c.index+c[0][f])>y&&(p.push(r.slice(y,c.index)),!s&&c[f]>1&&c[0].replace(e,function(){for(v=1;v<arguments[f]-2;v++)void 0===arguments[v]&&(c[v]=void 0)}),c[f]>1&&c.index<r[f]&&u.apply(p,c.slice(1)),h=c[0][f],y=l,p[f]>=g));)b[a]===c.index&&b[a]++;return y===r[f]?!h&&b.test("")||p.push(""):p.push(r.slice(y)),p[f]>g?p.slice(0,g):p}}else"0"[c](void 0,0)[f]&&(e=function(t,n){return void 0===t&&0===n?[]:o.call(this,t,n)});return[function(r,i){var o=t(this),u=void 0==r?void 0:r[n];return void 0!==u?u.call(r,o,i):e.call(String(o),r,i)},e]})},function(t,n,r){"use strict";r(184);var e=r(2),i=r(120),o=r(10),u="toString",c=/./[u],f=function(t){r(28)(RegExp.prototype,u,t,!0)};r(4)(function(){return"/a/b"!=c.call({source:"a",flags:"b"})})?f(function(){var t=e(this);return"/".concat(t.source,"/","flags"in t?t.flags:!o&&t instanceof RegExp?i.call(t):void 0)}):c.name!=u&&f(function(){return c.call(this)})},function(t,n,r){"use strict";r(29)("anchor",function(t){return function(n){return t(this,"a","name",n)}})},function(t,n,r){"use strict";r(29)("big",function(t){return function(){return t(this,"big","","")}})},function(t,n,r){"use strict";r(29)("blink",function(t){return function(){return t(this,"blink","","")}})},function(t,n,r){"use strict";r(29)("bold",function(t){return function(){return t(this,"b","","")}})},function(t,n,r){"use strict";var e=r(1),i=r(147)(!1);e(e.P,"String",{codePointAt:function(t){return i(this,t)}})},function(t,n,r){"use strict";var e=r(1),i=r(16),o=r(148),u="endsWith",c=""[u];e(e.P+e.F*r(134)(u),"String",{endsWith:function(t){var n=o(this,t,u),r=arguments.length>1?arguments[1]:void 0,e=i(n.length),f=void 0===r?e:Math.min(i(r),e),a=String(t);return c?c.call(n,a,f):n.slice(f-a.length,f)===a}})},function(t,n,r){"use strict";r(29)("fixed",function(t){return function(){return t(this,"tt","","")}})},function(t,n,r){"use strict";r(29)("fontcolor",function(t){return function(n){return t(this,"font","color",n)}})},function(t,n,r){"use strict";r(29)("fontsize",function(t){return function(n){return t(this,"font","size",n)}})},function(t,n,r){var e=r(1),i=r(75),o=String.fromCharCode,u=String.fromCodePoint;e(e.S+e.F*(!!u&&1!=u.length),"String",{fromCodePoint:function(t){for(var n,r=[],e=arguments.length,u=0;e>u;){if(n=+arguments[u++],i(n,1114111)!==n)throw RangeError(n+" is not a valid code point");r.push(n<65536?o(n):o(55296+((n-=65536)>>10),n%1024+56320))}return r.join("")}})},function(t,n,r){"use strict";var e=r(1),i=r(148),o="includes";e(e.P+e.F*r(134)(o),"String",{includes:function(t){return!!~i(this,t,o).indexOf(t,arguments.length>1?arguments[1]:void 0)}})},function(t,n,r){"use strict";r(29)("italics",function(t){return function(){return t(this,"i","","")}})},function(t,n,r){"use strict";var e=r(147)(!0);r(140)(String,"String",function(t){this._t=String(t),this._i=0},function(){var t,n=this._t,r=this._i;return r>=n.length?{value:void 0,done:!0}:(t=e(n,r),this._i+=t.length,{value:t,done:!1})})},function(t,n,r){"use strict";r(29)("link",function(t){return function(n){return t(this,"a","href",n)}})},function(t,n,r){var e=r(1),i=r(30),o=r(16);e(e.S,"String",{raw:function(t){for(var n=i(t.raw),r=o(n.length),e=arguments.length,u=[],c=0;r>c;)u.push(String(n[c++])),c<e&&u.push(String(arguments[c]));return u.join("")}})},function(t,n,r){var e=r(1);e(e.P,"String",{repeat:r(149)})},function(t,n,r){"use strict";r(29)("small",function(t){return function(){return t(this,"small","","")}})},function(t,n,r){"use strict";var e=r(1),i=r(16),o=r(148),u="startsWith",c=""[u];e(e.P+e.F*r(134)(u),"String",{startsWith:function(t){var n=o(this,t,u),r=i(Math.min(arguments.length>1?arguments[1]:void 0,n.length)),e=String(t);return c?c.call(n,e,r):n.slice(r,r+e.length)===e}})},function(t,n,r){"use strict";r(29)("strike",function(t){return function(){return t(this,"strike","","")}})},function(t,n,r){"use strict";r(29)("sub",function(t){return function(){return t(this,"sub","","")}})},function(t,n,r){"use strict";r(29)("sup",function(t){return function(){return t(this,"sup","","")}})},function(t,n,r){"use strict";r(82)("trim",function(t){return function(){return t(this,3)}})},function(t,n,r){"use strict";var e=r(3),i=r(24),o=r(10),u=r(1),c=r(28),f=r(65).KEY,a=r(4),s=r(126),l=r(81),h=r(76),v=r(7),p=r(182),d=r(153),y=r(206),g=r(205),b=r(138),m=r(2),x=r(30),w=r(50),S=r(66),_=r(70),O=r(174),E=r(31),P=r(11),j=r(72),F=E.f,M=P.f,A=O.f,N=e.Symbol,T=e.JSON,I=T&&T.stringify,k="prototype",L=v("_hidden"),R=v("toPrimitive"),C={}.propertyIsEnumerable,D=s("symbol-registry"),U=s("symbols"),W=s("op-symbols"),G=Object[k],B="function"==typeof N,V=e.QObject,z=!V||!V[k]||!V[k].findChild,q=o&&a(function(){return 7!=_(M({},"a",{get:function(){return M(this,"a",{value:7}).a}})).a})?function(t,n,r){var e=F(G,n);e&&delete G[n],M(t,n,r),e&&t!==G&&M(G,n,e)}:M,K=function(t){var n=U[t]=_(N[k]);return n._k=t,n},J=B&&"symbol"==typeof N.iterator?function(t){return"symbol"==typeof t}:function(t){return t instanceof N},Y=function(t,n,r){return t===G&&Y(W,n,r),m(t),n=w(n,!0),m(r),i(U,n)?(r.enumerable?(i(t,L)&&t[L][n]&&(t[L][n]=!1),r=_(r,{enumerable:S(0,!1)})):(i(t,L)||M(t,L,S(1,{})),t[L][n]=!0),q(t,n,r)):M(t,n,r)},H=function(t,n){m(t);for(var r,e=g(n=x(n)),i=0,o=e.length;o>i;)Y(t,r=e[i++],n[r]);return t},$=function(t,n){return void 0===n?_(t):H(_(t),n)},X=function(t){var n=C.call(this,t=w(t,!0));return!(this===G&&i(U,t)&&!i(W,t))&&(!(n||!i(this,t)||!i(U,t)||i(this,L)&&this[L][t])||n)},Q=function(t,n){if(t=x(t),n=w(n,!0),t!==G||!i(U,n)||i(W,n)){var r=F(t,n);return!r||!i(U,n)||i(t,L)&&t[L][n]||(r.enumerable=!0),r}},Z=function(t){for(var n,r=A(x(t)),e=[],o=0;r.length>o;)i(U,n=r[o++])||n==L||n==f||e.push(n);return e},tt=function(t){for(var n,r=t===G,e=A(r?W:x(t)),o=[],u=0;e.length>u;)!i(U,n=e[u++])||r&&!i(G,n)||o.push(U[n]);return o};B||(N=function(){if(this instanceof N)throw TypeError("Symbol is not a constructor!");var t=h(arguments.length>0?arguments[0]:void 0),n=function(r){this===G&&n.call(W,r),i(this,L)&&i(this[L],t)&&(this[L][t]=!1),q(this,t,S(1,r))};return o&&z&&q(G,t,{configurable:!0,set:n}),K(t)},c(N[k],"toString",function(){return this._k}),E.f=Q,P.f=Y,r(71).f=O.f=Z,r(116).f=X,r(125).f=tt,o&&!r(69)&&c(G,"propertyIsEnumerable",X,!0),p.f=function(t){return K(v(t))}),u(u.G+u.W+u.F*!B,{Symbol:N});for(var nt="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),rt=0;nt.length>rt;)v(nt[rt++]);for(var nt=j(v.store),rt=0;nt.length>rt;)d(nt[rt++]);u(u.S+u.F*!B,"Symbol",{for:function(t){return i(D,t+="")?D[t]:D[t]=N(t)},keyFor:function(t){if(J(t))return y(D,t);throw TypeError(t+" is not a symbol!")},useSetter:function(){z=!0},useSimple:function(){z=!1}}),u(u.S+u.F*!B,"Object",{create:$,defineProperty:Y,defineProperties:H,getOwnPropertyDescriptor:Q,getOwnPropertyNames:Z,getOwnPropertySymbols:tt}),T&&u(u.S+u.F*(!B||a(function(){var t=N();return"[null]"!=I([t])||"{}"!=I({a:t})||"{}"!=I(Object(t))})),"JSON",{stringify:function(t){if(void 0!==t&&!J(t)){for(var n,r,e=[t],i=1;arguments.length>i;)e.push(arguments[i++]);return n=e[1],"function"==typeof n&&(r=n),!r&&b(n)||(n=function(t,n){if(r&&(n=r.call(this,t,n)),!J(n))return n}),e[1]=n,I.apply(T,e)}}}),N[k][R]||r(27)(N[k],R,N[k].valueOf),l(N,"Symbol"),l(Math,"Math",!0),l(e.JSON,"JSON",!0)},function(t,n,r){"use strict";var e=r(1),i=r(127),o=r(152),u=r(2),c=r(75),f=r(16),a=r(6),s=r(3).ArrayBuffer,l=r(146),h=o.ArrayBuffer,v=o.DataView,p=i.ABV&&s.isView,d=h.prototype.slice,y=i.VIEW,g="ArrayBuffer";e(e.G+e.W+e.F*(s!==h),{ArrayBuffer:h}),e(e.S+e.F*!i.CONSTR,g,{isView:function(t){return p&&p(t)||a(t)&&y in t}}),e(e.P+e.U+e.F*r(4)(function(){return!new h(2).slice(1,void 0).byteLength}),g,{slice:function(t,n){if(void 0!==d&&void 0===n)return d.call(u(this),t);for(var r=u(this).byteLength,e=c(t,r),i=c(void 0===n?r:n,r),o=new(l(this,h))(f(i-e)),a=new v(this),s=new v(o),p=0;e<i;)s.setUint8(p++,a.getUint8(e++));return o}}),r(74)(g)},function(t,n,r){var e=r(1);e(e.G+e.W+e.F*!r(127).ABV,{DataView:r(152).DataView})},function(t,n,r){r(55)("Float32",4,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Float64",8,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Int16",2,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Int32",4,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Int8",1,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Uint16",2,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Uint32",4,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Uint8",1,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Uint8",1,function(t){return function(n,r,e){return t(this,n,r,e)}},!0)},function(t,n,r){"use strict";var e=r(166);r(118)("WeakSet",function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{add:function(t){return e.def(this,t,!0)}},e,!1,!0)},function(t,n,r){"use strict";var e=r(1),i=r(117)(!0);e(e.P,"Array",{includes:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}}),r(78)("includes")},function(t,n,r){var e=r(1),i=r(143)(),o=r(3).process,u="process"==r(45)(o);e(e.G,{asap:function(t){var n=u&&o.domain;i(n?n.bind(t):t)}})},function(t,n,r){var e=r(1),i=r(45);e(e.S,"Error",{isError:function(t){return"Error"===i(t)}})},function(t,n,r){var e=r(1);e(e.P+e.R,"Map",{toJSON:r(165)("Map")})},function(t,n,r){var e=r(1);e(e.S,"Math",{iaddh:function(t,n,r,e){var i=t>>>0,o=n>>>0,u=r>>>0;return o+(e>>>0)+((i&u|(i|u)&~(i+u>>>0))>>>31)|0}})},function(t,n,r){var e=r(1);e(e.S,"Math",{imulh:function(t,n){var r=65535,e=+t,i=+n,o=e&r,u=i&r,c=e>>16,f=i>>16,a=(c*u>>>0)+(o*u>>>16);return c*f+(a>>16)+((o*f>>>0)+(a&r)>>16)}})},function(t,n,r){var e=r(1);e(e.S,"Math",{isubh:function(t,n,r,e){var i=t>>>0,o=n>>>0,u=r>>>0;return o-(e>>>0)-((~i&u|~(i^u)&i-u>>>0)>>>31)|0}})},function(t,n,r){var e=r(1);e(e.S,"Math",{umulh:function(t,n){var r=65535,e=+t,i=+n,o=e&r,u=i&r,c=e>>>16,f=i>>>16,a=(c*u>>>0)+(o*u>>>16);return c*f+(a>>>16)+((o*f>>>0)+(a&r)>>>16)}})},function(t,n,r){"use strict";var e=r(1),i=r(17),o=r(26),u=r(11);r(10)&&e(e.P+r(124),"Object",{__defineGetter__:function(t,n){u.f(i(this),t,{get:o(n),enumerable:!0,configurable:!0})}})},function(t,n,r){"use strict";var e=r(1),i=r(17),o=r(26),u=r(11);r(10)&&e(e.P+r(124),"Object",{__defineSetter__:function(t,n){u.f(i(this),t,{set:o(n),enumerable:!0,configurable:!0})}})},function(t,n,r){var e=r(1),i=r(176)(!0);e(e.S,"Object",{entries:function(t){return i(t)}})},function(t,n,r){var e=r(1),i=r(177),o=r(30),u=r(31),c=r(131);e(e.S,"Object",{getOwnPropertyDescriptors:function(t){for(var n,r=o(t),e=u.f,f=i(r),a={},s=0;f.length>s;)c(a,n=f[s++],e(r,n));return a}})},function(t,n,r){"use strict";var e=r(1),i=r(17),o=r(50),u=r(32),c=r(31).f;r(10)&&e(e.P+r(124),"Object",{__lookupGetter__:function(t){var n,r=i(this),e=o(t,!0);do{if(n=c(r,e))return n.get}while(r=u(r))}})},function(t,n,r){"use strict";var e=r(1),i=r(17),o=r(50),u=r(32),c=r(31).f;r(10)&&e(e.P+r(124),"Object",{__lookupSetter__:function(t){var n,r=i(this),e=o(t,!0);do{if(n=c(r,e))return n.set}while(r=u(r))}})},function(t,n,r){var e=r(1),i=r(176)(!1);e(e.S,"Object",{values:function(t){return i(t)}})},function(t,n,r){"use strict";var e=r(1),i=r(3),o=r(52),u=r(143)(),c=r(7)("observable"),f=r(26),a=r(2),s=r(68),l=r(73),h=r(27),v=r(79),p=v.RETURN,d=function(t){return null==t?void 0:f(t)},y=function(t){var n=t._c;n&&(t._c=void 0,n())},g=function(t){return void 0===t._o},b=function(t){g(t)||(t._o=void 0,y(t))},m=function(t,n){a(t),this._c=void 0,this._o=t,t=new x(this);try{var r=n(t),e=r;null!=r&&("function"==typeof r.unsubscribe?r=function(){e.unsubscribe()}:f(r),this._c=r)}catch(n){return void t.error(n)}g(this)&&y(this)};m.prototype=l({},{unsubscribe:function(){b(this)}});var x=function(t){this._s=t};x.prototype=l({},{next:function(t){var n=this._s;if(!g(n)){var r=n._o;try{var e=d(r.next);if(e)return e.call(r,t)}catch(t){try{b(n)}finally{throw t}}}},error:function(t){var n=this._s;if(g(n))throw t;var r=n._o;n._o=void 0;try{var e=d(r.error);if(!e)throw t;t=e.call(r,t)}catch(t){try{y(n)}finally{throw t}}return y(n),t},complete:function(t){var n=this._s;if(!g(n)){var r=n._o;n._o=void 0;try{var e=d(r.complete);t=e?e.call(r,t):void 0}catch(t){try{y(n)}finally{throw t}}return y(n),t}}});var w=function(t){s(this,w,"Observable","_f")._f=f(t)};l(w.prototype,{subscribe:function(t){return new m(t,this._f)},forEach:function(t){var n=this;return new(o.Promise||i.Promise)(function(r,e){f(t);var i=n.subscribe({next:function(n){try{return t(n)}catch(t){e(t),i.unsubscribe()}},error:e,complete:r})})}}),l(w,{from:function(t){var n="function"==typeof this?this:w,r=d(a(t)[c]);if(r){var e=a(r.call(t));return e.constructor===n?e:new n(function(t){return e.subscribe(t)})}return new n(function(n){var r=!1;return u(function(){if(!r){try{if(v(t,!1,function(t){if(n.next(t),r)return p})===p)return}catch(t){if(r)throw t;return void n.error(t)}n.complete()}}),function(){r=!0}})},of:function(){for(var t=0,n=arguments.length,r=Array(n);t<n;)r[t]=arguments[t++];return new("function"==typeof this?this:w)(function(t){var n=!1;return u(function(){if(!n){for(var e=0;e<r.length;++e)if(t.next(r[e]),n)return;t.complete()}}),function(){n=!0}})}}),h(w.prototype,c,function(){return this}),e(e.G,{Observable:w}),r(74)("Observable")},function(t,n,r){var e=r(54),i=r(2),o=e.key,u=e.set;e.exp({defineMetadata:function(t,n,r,e){u(t,n,i(r),o(e))}})},function(t,n,r){var e=r(54),i=r(2),o=e.key,u=e.map,c=e.store;e.exp({deleteMetadata:function(t,n){var r=arguments.length<3?void 0:o(arguments[2]),e=u(i(n),r,!1);if(void 0===e||!e.delete(t))return!1;if(e.size)return!0;var f=c.get(n);return f.delete(r),!!f.size||c.delete(n)}})},function(t,n,r){var e=r(185),i=r(161),o=r(54),u=r(2),c=r(32),f=o.keys,a=o.key,s=function(t,n){var r=f(t,n),o=c(t);if(null===o)return r;var u=s(o,n);return u.length?r.length?i(new e(r.concat(u))):u:r};o.exp({getMetadataKeys:function(t){return s(u(t),arguments.length<2?void 0:a(arguments[1]))}})},function(t,n,r){var e=r(54),i=r(2),o=r(32),u=e.has,c=e.get,f=e.key,a=function(t,n,r){if(u(t,n,r))return c(t,n,r);var e=o(n);return null!==e?a(t,e,r):void 0};e.exp({getMetadata:function(t,n){return a(t,i(n),arguments.length<3?void 0:f(arguments[2]))}})},function(t,n,r){var e=r(54),i=r(2),o=e.keys,u=e.key;e.exp({getOwnMetadataKeys:function(t){
return o(i(t),arguments.length<2?void 0:u(arguments[1]))}})},function(t,n,r){var e=r(54),i=r(2),o=e.get,u=e.key;e.exp({getOwnMetadata:function(t,n){return o(t,i(n),arguments.length<3?void 0:u(arguments[2]))}})},function(t,n,r){var e=r(54),i=r(2),o=r(32),u=e.has,c=e.key,f=function(t,n,r){if(u(t,n,r))return!0;var e=o(n);return null!==e&&f(t,e,r)};e.exp({hasMetadata:function(t,n){return f(t,i(n),arguments.length<3?void 0:c(arguments[2]))}})},function(t,n,r){var e=r(54),i=r(2),o=e.has,u=e.key;e.exp({hasOwnMetadata:function(t,n){return o(t,i(n),arguments.length<3?void 0:u(arguments[2]))}})},function(t,n,r){var e=r(54),i=r(2),o=r(26),u=e.key,c=e.set;e.exp({metadata:function(t,n){return function(r,e){c(t,n,(void 0!==e?i:o)(r),u(e))}}})},function(t,n,r){var e=r(1);e(e.P+e.R,"Set",{toJSON:r(165)("Set")})},function(t,n,r){"use strict";var e=r(1),i=r(147)(!0);e(e.P,"String",{at:function(t){return i(this,t)}})},function(t,n,r){"use strict";var e=r(1),i=r(46),o=r(16),u=r(122),c=r(120),f=RegExp.prototype,a=function(t,n){this._r=t,this._s=n};r(139)(a,"RegExp String",function(){var t=this._r.exec(this._s);return{value:t,done:null===t}}),e(e.P,"String",{matchAll:function(t){if(i(this),!u(t))throw TypeError(t+" is not a regexp!");var n=String(this),r="flags"in f?String(t.flags):c.call(t),e=new RegExp(t.source,~r.indexOf("g")?r:"g"+r);return e.lastIndex=o(t.lastIndex),new a(e,n)}})},function(t,n,r){"use strict";var e=r(1),i=r(181);e(e.P,"String",{padEnd:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0,!1)}})},function(t,n,r){"use strict";var e=r(1),i=r(181);e(e.P,"String",{padStart:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0,!0)}})},function(t,n,r){"use strict";r(82)("trimLeft",function(t){return function(){return t(this,1)}},"trimStart")},function(t,n,r){"use strict";r(82)("trimRight",function(t){return function(){return t(this,2)}},"trimEnd")},function(t,n,r){r(153)("asyncIterator")},function(t,n,r){r(153)("observable")},function(t,n,r){var e=r(1);e(e.S,"System",{global:r(3)})},function(t,n,r){for(var e=r(155),i=r(28),o=r(3),u=r(27),c=r(80),f=r(7),a=f("iterator"),s=f("toStringTag"),l=c.Array,h=["NodeList","DOMTokenList","MediaList","StyleSheetList","CSSRuleList"],v=0;v<5;v++){var p,d=h[v],y=o[d],g=y&&y.prototype;if(g){g[a]||u(g,a,l),g[s]||u(g,s,d),c[d]=l;for(p in e)g[p]||i(g,p,e[p],!0)}}},function(t,n,r){var e=r(1),i=r(151);e(e.G+e.B,{setImmediate:i.set,clearImmediate:i.clear})},function(t,n,r){var e=r(3),i=r(1),o=r(121),u=r(207),c=e.navigator,f=!!c&&/MSIE .\./.test(c.userAgent),a=function(t){return f?function(n,r){return t(o(u,[].slice.call(arguments,2),"function"==typeof n?n:Function(n)),r)}:t};i(i.G+i.B+i.F*f,{setTimeout:a(e.setTimeout),setInterval:a(e.setInterval)})},function(t,n,r){r(330),r(269),r(271),r(270),r(273),r(275),r(280),r(274),r(272),r(282),r(281),r(277),r(278),r(276),r(268),r(279),r(283),r(284),r(236),r(238),r(237),r(286),r(285),r(256),r(266),r(267),r(257),r(258),r(259),r(260),r(261),r(262),r(263),r(264),r(265),r(239),r(240),r(241),r(242),r(243),r(244),r(245),r(246),r(247),r(248),r(249),r(250),r(251),r(252),r(253),r(254),r(255),r(317),r(322),r(329),r(320),r(312),r(313),r(318),r(323),r(325),r(308),r(309),r(310),r(311),r(314),r(315),r(316),r(319),r(321),r(324),r(326),r(327),r(328),r(231),r(233),r(232),r(235),r(234),r(220),r(218),r(224),r(221),r(227),r(229),r(217),r(223),r(214),r(228),r(212),r(226),r(225),r(219),r(222),r(211),r(213),r(216),r(215),r(230),r(155),r(302),r(307),r(184),r(303),r(304),r(305),r(306),r(287),r(183),r(185),r(186),r(342),r(331),r(332),r(337),r(340),r(341),r(335),r(338),r(336),r(339),r(333),r(334),r(288),r(289),r(290),r(291),r(292),r(295),r(293),r(294),r(296),r(297),r(298),r(299),r(301),r(300),r(343),r(369),r(372),r(371),r(373),r(374),r(370),r(375),r(376),r(354),r(357),r(353),r(351),r(352),r(355),r(356),r(346),r(368),r(377),r(345),r(347),r(349),r(348),r(350),r(359),r(360),r(362),r(361),r(364),r(363),r(365),r(366),r(367),r(344),r(358),r(380),r(379),r(378),t.exports=r(52)},function(t,n){function r(t,n){if("string"==typeof n)return t.insertAdjacentHTML("afterend",n);var r=t.nextSibling;return r?t.parentNode.insertBefore(n,r):t.parentNode.appendChild(n)}t.exports=r},,,,,,,,,function(t,n,r){(function(n,r){!function(n){"use strict";function e(t,n,r,e){var i=n&&n.prototype instanceof o?n:o,u=Object.create(i.prototype),c=new p(e||[]);return u._invoke=s(t,r,c),u}function i(t,n,r){try{return{type:"normal",arg:t.call(n,r)}}catch(t){return{type:"throw",arg:t}}}function o(){}function u(){}function c(){}function f(t){["next","throw","return"].forEach(function(n){t[n]=function(t){return this._invoke(n,t)}})}function a(t){function n(r,e,o,u){var c=i(t[r],t,e);if("throw"!==c.type){var f=c.arg,a=f.value;return a&&"object"==typeof a&&m.call(a,"__await")?Promise.resolve(a.__await).then(function(t){n("next",t,o,u)},function(t){n("throw",t,o,u)}):Promise.resolve(a).then(function(t){f.value=t,o(f)},u)}u(c.arg)}function e(t,r){function e(){return new Promise(function(e,i){n(t,r,e,i)})}return o=o?o.then(e,e):e()}"object"==typeof r&&r.domain&&(n=r.domain.bind(n));var o;this._invoke=e}function s(t,n,r){var e=P;return function(o,u){if(e===F)throw new Error("Generator is already running");if(e===M){if("throw"===o)throw u;return y()}for(r.method=o,r.arg=u;;){var c=r.delegate;if(c){var f=l(c,r);if(f){if(f===A)continue;return f}}if("next"===r.method)r.sent=r._sent=r.arg;else if("throw"===r.method){if(e===P)throw e=M,r.arg;r.dispatchException(r.arg)}else"return"===r.method&&r.abrupt("return",r.arg);e=F;var a=i(t,n,r);if("normal"===a.type){if(e=r.done?M:j,a.arg===A)continue;return{value:a.arg,done:r.done}}"throw"===a.type&&(e=M,r.method="throw",r.arg=a.arg)}}}function l(t,n){var r=t.iterator[n.method];if(r===g){if(n.delegate=null,"throw"===n.method){if(t.iterator.return&&(n.method="return",n.arg=g,l(t,n),"throw"===n.method))return A;n.method="throw",n.arg=new TypeError("The iterator does not provide a 'throw' method")}return A}var e=i(r,t.iterator,n.arg);if("throw"===e.type)return n.method="throw",n.arg=e.arg,n.delegate=null,A;var o=e.arg;return o?o.done?(n[t.resultName]=o.value,n.next=t.nextLoc,"return"!==n.method&&(n.method="next",n.arg=g),n.delegate=null,A):o:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,A)}function h(t){var n={tryLoc:t[0]};1 in t&&(n.catchLoc=t[1]),2 in t&&(n.finallyLoc=t[2],n.afterLoc=t[3]),this.tryEntries.push(n)}function v(t){var n=t.completion||{};n.type="normal",delete n.arg,t.completion=n}function p(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(h,this),this.reset(!0)}function d(t){if(t){var n=t[w];if(n)return n.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var r=-1,e=function n(){for(;++r<t.length;)if(m.call(t,r))return n.value=t[r],n.done=!1,n;return n.value=g,n.done=!0,n};return e.next=e}}return{next:y}}function y(){return{value:g,done:!0}}var g,b=Object.prototype,m=b.hasOwnProperty,x="function"==typeof Symbol?Symbol:{},w=x.iterator||"@@iterator",S=x.asyncIterator||"@@asyncIterator",_=x.toStringTag||"@@toStringTag",O="object"==typeof t,E=n.regeneratorRuntime;if(E)return void(O&&(t.exports=E));E=n.regeneratorRuntime=O?t.exports:{},E.wrap=e;var P="suspendedStart",j="suspendedYield",F="executing",M="completed",A={},N={};N[w]=function(){return this};var T=Object.getPrototypeOf,I=T&&T(T(d([])));I&&I!==b&&m.call(I,w)&&(N=I);var k=c.prototype=o.prototype=Object.create(N);u.prototype=k.constructor=c,c.constructor=u,c[_]=u.displayName="GeneratorFunction",E.isGeneratorFunction=function(t){var n="function"==typeof t&&t.constructor;return!!n&&(n===u||"GeneratorFunction"===(n.displayName||n.name))},E.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,c):(t.__proto__=c,_ in t||(t[_]="GeneratorFunction")),t.prototype=Object.create(k),t},E.awrap=function(t){return{__await:t}},f(a.prototype),a.prototype[S]=function(){return this},E.AsyncIterator=a,E.async=function(t,n,r,i){var o=new a(e(t,n,r,i));return E.isGeneratorFunction(n)?o:o.next().then(function(t){return t.done?t.value:o.next()})},f(k),k[_]="Generator",k.toString=function(){return"[object Generator]"},E.keys=function(t){var n=[];for(var r in t)n.push(r);return n.reverse(),function r(){for(;n.length;){var e=n.pop();if(e in t)return r.value=e,r.done=!1,r}return r.done=!0,r}},E.values=d,p.prototype={constructor:p,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=g,this.done=!1,this.delegate=null,this.method="next",this.arg=g,this.tryEntries.forEach(v),!t)for(var n in this)"t"===n.charAt(0)&&m.call(this,n)&&!isNaN(+n.slice(1))&&(this[n]=g)},stop:function(){this.done=!0;var t=this.tryEntries[0],n=t.completion;if("throw"===n.type)throw n.arg;return this.rval},dispatchException:function(t){function n(n,e){return o.type="throw",o.arg=t,r.next=n,e&&(r.method="next",r.arg=g),!!e}if(this.done)throw t;for(var r=this,e=this.tryEntries.length-1;e>=0;--e){var i=this.tryEntries[e],o=i.completion;if("root"===i.tryLoc)return n("end");if(i.tryLoc<=this.prev){var u=m.call(i,"catchLoc"),c=m.call(i,"finallyLoc");if(u&&c){if(this.prev<i.catchLoc)return n(i.catchLoc,!0);if(this.prev<i.finallyLoc)return n(i.finallyLoc)}else if(u){if(this.prev<i.catchLoc)return n(i.catchLoc,!0)}else{if(!c)throw new Error("try statement without catch or finally");if(this.prev<i.finallyLoc)return n(i.finallyLoc)}}}},abrupt:function(t,n){for(var r=this.tryEntries.length-1;r>=0;--r){var e=this.tryEntries[r];if(e.tryLoc<=this.prev&&m.call(e,"finallyLoc")&&this.prev<e.finallyLoc){var i=e;break}}i&&("break"===t||"continue"===t)&&i.tryLoc<=n&&n<=i.finallyLoc&&(i=null);var o=i?i.completion:{};return o.type=t,o.arg=n,i?(this.method="next",this.next=i.finallyLoc,A):this.complete(o)},complete:function(t,n){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&n&&(this.next=n),A},finish:function(t){for(var n=this.tryEntries.length-1;n>=0;--n){var r=this.tryEntries[n];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),v(r),A}},catch:function(t){for(var n=this.tryEntries.length-1;n>=0;--n){var r=this.tryEntries[n];if(r.tryLoc===t){var e=r.completion;if("throw"===e.type){var i=e.arg;v(r)}return i}}throw new Error("illegal catch attempt")},delegateYield:function(t,n,r){return this.delegate={iterator:d(t),resultName:n,nextLoc:r},"next"===this.method&&(this.arg=g),A}}}("object"==typeof n?n:"object"==typeof window?window:"object"==typeof self?self:this)}).call(n,function(){return this}(),r(158))}])</script><script src="/blog/./main.0cf68a.js"></script><script>!function(){!function(e){var t=document.createElement("script");document.getElementsByTagName("body")[0].appendChild(t),t.setAttribute("src",e)}("/blog/slider.e37972.js")}()</script>


    
<div class="tools-col" q-class="show:isShow,hide:isShow|isFalse" q-on="click:stop(e)">
  <div class="tools-nav header-menu">
    
    
      
      
      
    
      
      
      
    
      
      
      
    
    

    <ul style="width: 70%">
    
    
      
      <li style="width: 33.333333333333336%" q-on="click: openSlider(e, 'innerArchive')"><a href="javascript:void(0)" q-class="active:innerArchive">所有文章</a></li>
      
        
      
      <li style="width: 33.333333333333336%" q-on="click: openSlider(e, 'friends')"><a href="javascript:void(0)" q-class="active:friends">友链</a></li>
      
        
      
      <li style="width: 33.333333333333336%" q-on="click: openSlider(e, 'aboutme')"><a href="javascript:void(0)" q-class="active:aboutme">关于我</a></li>
      
        
    </ul>
  </div>
  <div class="tools-wrap">
    
    	<section class="tools-section tools-section-all" q-show="innerArchive">
        <div class="search-wrap">
          <input class="search-ipt" q-model="search" type="text" placeholder="find something…">
          <i class="icon-search icon" q-show="search|isEmptyStr"></i>
          <i class="icon-close icon" q-show="search|isNotEmptyStr" q-on="click:clearChose(e)"></i>
        </div>
        <div class="widget tagcloud search-tag">
          <p class="search-tag-wording">tag:</p>
          <label class="search-switch">
            <input type="checkbox" q-on="click:toggleTag(e)" q-attr="checked:showTags">
          </label>
          <ul class="article-tag-list" q-show="showTags">
            
            <div class="clearfix"></div>
          </ul>
        </div>
        <ul class="search-ul">
          <p q-show="jsonFail" style="padding: 20px; font-size: 12px;">
            缺失模块。<br/>1、请确保node版本大于6.2<br/>2、在博客根目录（注意不是yilia根目录）执行以下命令：<br/> npm i hexo-generator-json-content --save<br/><br/>
            3、在根目录_config.yml里添加配置：
<pre style="font-size: 12px;" q-show="jsonFail">
  jsonContent:
    meta: false
    pages: false
    posts:
      title: true
      date: true
      path: true
      text: false
      raw: false
      content: false
      slug: false
      updated: false
      comments: false
      link: false
      permalink: false
      excerpt: false
      categories: false
      tags: true
</pre>
          </p>
          <li class="search-li" q-repeat="items" q-show="isShow">
            <a q-attr="href:path|urlformat" class="search-title"><i class="icon-quo-left icon"></i><span q-text="title"></span></a>
            <p class="search-time">
              <i class="icon-calendar icon"></i>
              <span q-text="date|dateformat"></span>
            </p>
            <p class="search-tag">
              <i class="icon-price-tags icon"></i>
              <span q-repeat="tags" q-on="click:choseTag(e, name)" q-text="name|tagformat"></span>
            </p>
          </li>
        </ul>
    	</section>
    

    
    	<section class="tools-section tools-section-friends" q-show="friends">
  		
        <ul class="search-ul">
          
            <li class="search-li">
              <a href="https://gitee.com/Eason_Mo/blog/pages" target="_blank" class="search-title"><i class="icon-quo-left icon"></i>友情链接1</a>
            </li>
          
            <li class="search-li">
              <a href="http://localhost:4000/" target="_blank" class="search-title"><i class="icon-quo-left icon"></i>友情链接2</a>
            </li>
          
            <li class="search-li">
              <a href="http://localhost:4000/" target="_blank" class="search-title"><i class="icon-quo-left icon"></i>友情链接3</a>
            </li>
          
            <li class="search-li">
              <a href="http://localhost:4000/" target="_blank" class="search-title"><i class="icon-quo-left icon"></i>友情链接4</a>
            </li>
          
            <li class="search-li">
              <a href="http://localhost:4000/" target="_blank" class="search-title"><i class="icon-quo-left icon"></i>友情链接5</a>
            </li>
          
            <li class="search-li">
              <a href="http://localhost:4000/" target="_blank" class="search-title"><i class="icon-quo-left icon"></i>友情链接6</a>
            </li>
          
        </ul>
  		
    	</section>
    

    
    	<section class="tools-section tools-section-me" q-show="aboutme">
  	  	
  	  		<div class="aboutme-wrap" id="js-aboutme">很惭愧&lt;br&gt;要么堕落，要么孤独&lt;br&gt;只做了一点微小的工作&lt;br&gt;谢谢大家</div>
  	  	
    	</section>
    
  </div>
  
</div>
    <!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">

    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>

    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">

        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>

        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">

            <div class="pswp__top-bar">

                <!--  Controls are self-explanatory. Order can be changed. -->

                <div class="pswp__counter"></div>

                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>

                <button class="pswp__button pswp__button--share" style="display:none" title="Share"></button>

                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>

                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>

                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                      <div class="pswp__preloader__cut">
                        <div class="pswp__preloader__donut"></div>
                      </div>
                    </div>
                </div>
            </div>

            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div> 
            </div>

            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>

            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>

            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>

        </div>

    </div>

</div>
  </div>
</body>
</html>